]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
don't load corrupt wav files
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155
156 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
162
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
167
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
175
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
180
181 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
182
183 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
184
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
186
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194
195 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
196 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
197
198 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
199
200 extern cvar_t v_glslgamma;
201
202 extern qboolean v_flipped_state;
203
204 static struct r_bloomstate_s
205 {
206         qboolean enabled;
207         qboolean hdr;
208
209         int bloomwidth, bloomheight;
210
211         int screentexturewidth, screentextureheight;
212         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
213
214         int bloomtexturewidth, bloomtextureheight;
215         rtexture_t *texture_bloom;
216
217         // arrays for rendering the screen passes
218         float screentexcoord2f[8];
219         float bloomtexcoord2f[8];
220         float offsettexcoord2f[8];
221
222         r_viewport_t viewport;
223 }
224 r_bloomstate;
225
226 r_waterstate_t r_waterstate;
227
228 /// shadow volume bsp struct with automatically growing nodes buffer
229 svbsp_t r_svbsp;
230
231 rtexture_t *r_texture_blanknormalmap;
232 rtexture_t *r_texture_white;
233 rtexture_t *r_texture_grey128;
234 rtexture_t *r_texture_black;
235 rtexture_t *r_texture_notexture;
236 rtexture_t *r_texture_whitecube;
237 rtexture_t *r_texture_normalizationcube;
238 rtexture_t *r_texture_fogattenuation;
239 rtexture_t *r_texture_fogheighttexture;
240 rtexture_t *r_texture_gammaramps;
241 unsigned int r_texture_gammaramps_serial;
242 //rtexture_t *r_texture_fogintensity;
243 rtexture_t *r_texture_reflectcube;
244
245 // TODO: hash lookups?
246 typedef struct cubemapinfo_s
247 {
248         char basename[64];
249         rtexture_t *texture;
250 }
251 cubemapinfo_t;
252
253 int r_texture_numcubemaps;
254 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
255
256 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
257 unsigned int r_numqueries;
258 unsigned int r_maxqueries;
259
260 typedef struct r_qwskincache_s
261 {
262         char name[MAX_QPATH];
263         skinframe_t *skinframe;
264 }
265 r_qwskincache_t;
266
267 static r_qwskincache_t *r_qwskincache;
268 static int r_qwskincache_size;
269
270 /// vertex coordinates for a quad that covers the screen exactly
271 extern const float r_screenvertex3f[12];
272 extern const float r_d3dscreenvertex3f[12];
273 const float r_screenvertex3f[12] =
274 {
275         0, 0, 0,
276         1, 0, 0,
277         1, 1, 0,
278         0, 1, 0
279 };
280 const float r_d3dscreenvertex3f[12] =
281 {
282         0, 1, 0,
283         1, 1, 0,
284         1, 0, 0,
285         0, 0, 0
286 };
287
288 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
289 {
290         int i;
291         for (i = 0;i < verts;i++)
292         {
293                 out[0] = in[0] * r;
294                 out[1] = in[1] * g;
295                 out[2] = in[2] * b;
296                 out[3] = in[3];
297                 in += 4;
298                 out += 4;
299         }
300 }
301
302 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = r;
308                 out[1] = g;
309                 out[2] = b;
310                 out[3] = a;
311                 out += 4;
312         }
313 }
314
315 // FIXME: move this to client?
316 void FOG_clear(void)
317 {
318         if (gamemode == GAME_NEHAHRA)
319         {
320                 Cvar_Set("gl_fogenable", "0");
321                 Cvar_Set("gl_fogdensity", "0.2");
322                 Cvar_Set("gl_fogred", "0.3");
323                 Cvar_Set("gl_foggreen", "0.3");
324                 Cvar_Set("gl_fogblue", "0.3");
325         }
326         r_refdef.fog_density = 0;
327         r_refdef.fog_red = 0;
328         r_refdef.fog_green = 0;
329         r_refdef.fog_blue = 0;
330         r_refdef.fog_alpha = 1;
331         r_refdef.fog_start = 0;
332         r_refdef.fog_end = 16384;
333         r_refdef.fog_height = 1<<30;
334         r_refdef.fog_fadedepth = 128;
335         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
336 }
337
338 static void R_BuildBlankTextures(void)
339 {
340         unsigned char data[4];
341         data[2] = 128; // normal X
342         data[1] = 128; // normal Y
343         data[0] = 255; // normal Z
344         data[3] = 128; // height
345         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346         data[0] = 255;
347         data[1] = 255;
348         data[2] = 255;
349         data[3] = 255;
350         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351         data[0] = 128;
352         data[1] = 128;
353         data[2] = 128;
354         data[3] = 255;
355         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 0;
357         data[1] = 0;
358         data[2] = 0;
359         data[3] = 255;
360         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 }
362
363 static void R_BuildNoTexture(void)
364 {
365         int x, y;
366         unsigned char pix[16][16][4];
367         // this makes a light grey/dark grey checkerboard texture
368         for (y = 0;y < 16;y++)
369         {
370                 for (x = 0;x < 16;x++)
371                 {
372                         if ((y < 8) ^ (x < 8))
373                         {
374                                 pix[y][x][0] = 128;
375                                 pix[y][x][1] = 128;
376                                 pix[y][x][2] = 128;
377                                 pix[y][x][3] = 255;
378                         }
379                         else
380                         {
381                                 pix[y][x][0] = 64;
382                                 pix[y][x][1] = 64;
383                                 pix[y][x][2] = 64;
384                                 pix[y][x][3] = 255;
385                         }
386                 }
387         }
388         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
389 }
390
391 static void R_BuildWhiteCube(void)
392 {
393         unsigned char data[6*1*1*4];
394         memset(data, 255, sizeof(data));
395         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNormalizationCube(void)
399 {
400         int x, y, side;
401         vec3_t v;
402         vec_t s, t, intensity;
403 #define NORMSIZE 64
404         unsigned char *data;
405         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
406         for (side = 0;side < 6;side++)
407         {
408                 for (y = 0;y < NORMSIZE;y++)
409                 {
410                         for (x = 0;x < NORMSIZE;x++)
411                         {
412                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
413                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
414                                 switch(side)
415                                 {
416                                 default:
417                                 case 0:
418                                         v[0] = 1;
419                                         v[1] = -t;
420                                         v[2] = -s;
421                                         break;
422                                 case 1:
423                                         v[0] = -1;
424                                         v[1] = -t;
425                                         v[2] = s;
426                                         break;
427                                 case 2:
428                                         v[0] = s;
429                                         v[1] = 1;
430                                         v[2] = t;
431                                         break;
432                                 case 3:
433                                         v[0] = s;
434                                         v[1] = -1;
435                                         v[2] = -t;
436                                         break;
437                                 case 4:
438                                         v[0] = s;
439                                         v[1] = -t;
440                                         v[2] = 1;
441                                         break;
442                                 case 5:
443                                         v[0] = -s;
444                                         v[1] = -t;
445                                         v[2] = -1;
446                                         break;
447                                 }
448                                 intensity = 127.0f / sqrt(DotProduct(v, v));
449                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
450                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
451                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
452                                 data[((side*64+y)*64+x)*4+3] = 255;
453                         }
454                 }
455         }
456         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
457         Mem_Free(data);
458 }
459
460 static void R_BuildFogTexture(void)
461 {
462         int x, b;
463 #define FOGWIDTH 256
464         unsigned char data1[FOGWIDTH][4];
465         //unsigned char data2[FOGWIDTH][4];
466         double d, r, alpha;
467
468         r_refdef.fogmasktable_start = r_refdef.fog_start;
469         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
470         r_refdef.fogmasktable_range = r_refdef.fogrange;
471         r_refdef.fogmasktable_density = r_refdef.fog_density;
472
473         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
474         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
475         {
476                 d = (x * r - r_refdef.fogmasktable_start);
477                 if(developer_extra.integer)
478                         Con_DPrintf("%f ", d);
479                 d = max(0, d);
480                 if (r_fog_exp2.integer)
481                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
482                 else
483                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
484                 if(developer_extra.integer)
485                         Con_DPrintf(" : %f ", alpha);
486                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
487                 if(developer_extra.integer)
488                         Con_DPrintf(" = %f\n", alpha);
489                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
490         }
491
492         for (x = 0;x < FOGWIDTH;x++)
493         {
494                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495                 data1[x][0] = b;
496                 data1[x][1] = b;
497                 data1[x][2] = b;
498                 data1[x][3] = 255;
499                 //data2[x][0] = 255 - b;
500                 //data2[x][1] = 255 - b;
501                 //data2[x][2] = 255 - b;
502                 //data2[x][3] = 255;
503         }
504         if (r_texture_fogattenuation)
505         {
506                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
507                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
508         }
509         else
510         {
511                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
513         }
514 }
515
516 static void R_BuildFogHeightTexture(void)
517 {
518         unsigned char *inpixels;
519         int size;
520         int x;
521         int y;
522         int j;
523         float c[4];
524         float f;
525         inpixels = NULL;
526         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
527         if (r_refdef.fogheighttexturename[0])
528                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
529         if (!inpixels)
530         {
531                 r_refdef.fog_height_tablesize = 0;
532                 if (r_texture_fogheighttexture)
533                         R_FreeTexture(r_texture_fogheighttexture);
534                 r_texture_fogheighttexture = NULL;
535                 if (r_refdef.fog_height_table2d)
536                         Mem_Free(r_refdef.fog_height_table2d);
537                 r_refdef.fog_height_table2d = NULL;
538                 if (r_refdef.fog_height_table1d)
539                         Mem_Free(r_refdef.fog_height_table1d);
540                 r_refdef.fog_height_table1d = NULL;
541                 return;
542         }
543         size = image_width;
544         r_refdef.fog_height_tablesize = size;
545         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
546         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
547         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
548         Mem_Free(inpixels);
549         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
550         // average fog color table accounting for every fog layer between a point
551         // and the camera.  (Note: attenuation is handled separately!)
552         for (y = 0;y < size;y++)
553         {
554                 for (x = 0;x < size;x++)
555                 {
556                         Vector4Clear(c);
557                         f = 0;
558                         if (x < y)
559                         {
560                                 for (j = x;j <= y;j++)
561                                 {
562                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
563                                         f++;
564                                 }
565                         }
566                         else
567                         {
568                                 for (j = x;j >= y;j--)
569                                 {
570                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571                                         f++;
572                                 }
573                         }
574                         f = 1.0f / f;
575                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
576                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
577                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
579                 }
580         }
581         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
582 }
583
584 //=======================================================================================================================================================
585
586 static const char *builtinshaderstring =
587 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
588 "// written by Forest 'LordHavoc' Hale\n"
589 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
590 "\n"
591 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
592 "# define USEFOG\n"
593 "#endif\n"
594 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
595 "#define USELIGHTMAP\n"
596 "#endif\n"
597 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
598 "#define USEEYEVECTOR\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESHADOWMAP2D\n"
602 "# ifdef GL_EXT_gpu_shader4\n"
603 "#   extension GL_EXT_gpu_shader4 : enable\n"
604 "# endif\n"
605 "# ifdef GL_ARB_texture_gather\n"
606 "#   extension GL_ARB_texture_gather : enable\n"
607 "# else\n"
608 "#   ifdef GL_AMD_texture_texture4\n"
609 "#     extension GL_AMD_texture_texture4 : enable\n"
610 "#   endif\n"
611 "# endif\n"
612 "#endif\n"
613 "\n"
614 "//#ifdef USESHADOWSAMPLER\n"
615 "//# extension GL_ARB_shadow : enable\n"
616 "//#endif\n"
617 "\n"
618 "//#ifdef __GLSL_CG_DATA_TYPES\n"
619 "//# define myhalf half\n"
620 "//# define myhalf2 half2\n"
621 "//# define myhalf3 half3\n"
622 "//# define myhalf4 half4\n"
623 "//#else\n"
624 "# define myhalf float\n"
625 "# define myhalf2 vec2\n"
626 "# define myhalf3 vec3\n"
627 "# define myhalf4 vec4\n"
628 "//#endif\n"
629 "\n"
630 "#ifdef VERTEX_SHADER\n"
631 "uniform mat4 ModelViewProjectionMatrix;\n"
632 "#endif\n"
633 "\n"
634 "#ifdef MODE_DEPTH_OR_SHADOW\n"
635 "#ifdef VERTEX_SHADER\n"
636 "void main(void)\n"
637 "{\n"
638 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
639 "}\n"
640 "#endif\n"
641 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "\n"
643 "\n"
644 "\n"
645 "\n"
646 "#ifdef MODE_SHOWDEPTH\n"
647 "#ifdef VERTEX_SHADER\n"
648 "void main(void)\n"
649 "{\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
652 "}\n"
653 "#endif\n"
654 "\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "void main(void)\n"
657 "{\n"
658 "       gl_FragColor = gl_Color;\n"
659 "}\n"
660 "#endif\n"
661 "#else // !MODE_SHOWDEPTH\n"
662 "\n"
663 "\n"
664 "\n"
665 "\n"
666 "#ifdef MODE_POSTPROCESS\n"
667 "varying vec2 TexCoord1;\n"
668 "varying vec2 TexCoord2;\n"
669 "\n"
670 "#ifdef VERTEX_SHADER\n"
671 "void main(void)\n"
672 "{\n"
673 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
674 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
675 "#ifdef USEBLOOM\n"
676 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "\n"
681 "#ifdef FRAGMENT_SHADER\n"
682 "uniform sampler2D Texture_First;\n"
683 "#ifdef USEBLOOM\n"
684 "uniform sampler2D Texture_Second;\n"
685 "uniform vec4 BloomColorSubtract;\n"
686 "#endif\n"
687 "#ifdef USEGAMMARAMPS\n"
688 "uniform sampler2D Texture_GammaRamps;\n"
689 "#endif\n"
690 "#ifdef USESATURATION\n"
691 "uniform float Saturation;\n"
692 "#endif\n"
693 "#ifdef USEVIEWTINT\n"
694 "uniform vec4 ViewTintColor;\n"
695 "#endif\n"
696 "//uncomment these if you want to use them:\n"
697 "uniform vec4 UserVec1;\n"
698 "uniform vec4 UserVec2;\n"
699 "// uniform vec4 UserVec3;\n"
700 "// uniform vec4 UserVec4;\n"
701 "// uniform float ClientTime;\n"
702 "uniform vec2 PixelSize;\n"
703 "void main(void)\n"
704 "{\n"
705 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
706 "#ifdef USEBLOOM\n"
707 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
708 "#endif\n"
709 "#ifdef USEVIEWTINT\n"
710 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
711 "#endif\n"
712 "\n"
713 "#ifdef USEPOSTPROCESSING\n"
714 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
715 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
716 "       float sobel = 1.0;\n"
717 "       // vec2 ts = textureSize(Texture_First, 0);\n"
718 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
719 "       vec2 px = PixelSize;\n"
720 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
722 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
725 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
726 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
727 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
728 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
729 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
730 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
731 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
732 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
733 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
734 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
735 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
736 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
737 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
738 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
739 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
740 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
741 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
742 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
743 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
744 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
751 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
752 "#endif\n"
753 "\n"
754 "#ifdef USESATURATION\n"
755 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
756 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
757 "       // 'vampire sight' effect, wheres red is compensated\n"
758 "       #ifdef SATURATION_REDCOMPENSATE\n"
759 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
760 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
761 "               gl_FragColor.r += rboost;\n"
762 "       #else\n"
763 "               // normal desaturation\n"
764 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
765 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
766 "       #endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USEGAMMARAMPS\n"
770 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
771 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
772 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
773 "#endif\n"
774 "}\n"
775 "#endif\n"
776 "#else // !MODE_POSTPROCESS\n"
777 "\n"
778 "\n"
779 "\n"
780 "\n"
781 "#ifdef MODE_GENERIC\n"
782 "#ifdef USEDIFFUSE\n"
783 "varying vec2 TexCoord1;\n"
784 "#endif\n"
785 "#ifdef USESPECULAR\n"
786 "varying vec2 TexCoord2;\n"
787 "#endif\n"
788 "#ifdef VERTEX_SHADER\n"
789 "void main(void)\n"
790 "{\n"
791 "       gl_FrontColor = gl_Color;\n"
792 "#ifdef USEDIFFUSE\n"
793 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
797 "#endif\n"
798 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
799 "}\n"
800 "#endif\n"
801 "\n"
802 "#ifdef FRAGMENT_SHADER\n"
803 "#ifdef USEDIFFUSE\n"
804 "uniform sampler2D Texture_First;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "uniform sampler2D Texture_Second;\n"
808 "#endif\n"
809 "\n"
810 "void main(void)\n"
811 "{\n"
812 "       gl_FragColor = gl_Color;\n"
813 "#ifdef USEDIFFUSE\n"
814 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
815 "#endif\n"
816 "\n"
817 "#ifdef USESPECULAR\n"
818 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
819 "# ifdef USECOLORMAPPING\n"
820 "       gl_FragColor *= tex2;\n"
821 "# endif\n"
822 "# ifdef USEGLOW\n"
823 "       gl_FragColor += tex2;\n"
824 "# endif\n"
825 "# ifdef USEVERTEXTEXTUREBLEND\n"
826 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
827 "# endif\n"
828 "#endif\n"
829 "}\n"
830 "#endif\n"
831 "#else // !MODE_GENERIC\n"
832 "\n"
833 "\n"
834 "\n"
835 "\n"
836 "#ifdef MODE_BLOOMBLUR\n"
837 "varying TexCoord;\n"
838 "#ifdef VERTEX_SHADER\n"
839 "void main(void)\n"
840 "{\n"
841 "       gl_FrontColor = gl_Color;\n"
842 "       TexCoord = gl_MultiTexCoord0.xy;\n"
843 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
844 "}\n"
845 "#endif\n"
846 "\n"
847 "#ifdef FRAGMENT_SHADER\n"
848 "uniform sampler2D Texture_First;\n"
849 "uniform vec4 BloomBlur_Parameters;\n"
850 "\n"
851 "void main(void)\n"
852 "{\n"
853 "       int i;\n"
854 "       vec2 tc = TexCoord;\n"
855 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
856 "       tc += BloomBlur_Parameters.xy;\n"
857 "       for (i = 1;i < SAMPLES;i++)\n"
858 "       {\n"
859 "               color += texture2D(Texture_First, tc).rgb;\n"
860 "               tc += BloomBlur_Parameters.xy;\n"
861 "       }\n"
862 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
863 "}\n"
864 "#endif\n"
865 "#else // !MODE_BLOOMBLUR\n"
866 "#ifdef MODE_REFRACTION\n"
867 "varying vec2 TexCoord;\n"
868 "varying vec4 ModelViewProjectionPosition;\n"
869 "uniform mat4 TexMatrix;\n"
870 "#ifdef VERTEX_SHADER\n"
871 "\n"
872 "void main(void)\n"
873 "{\n"
874 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
875 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
876 "       ModelViewProjectionPosition = gl_Position;\n"
877 "}\n"
878 "#endif\n"
879 "\n"
880 "#ifdef FRAGMENT_SHADER\n"
881 "uniform sampler2D Texture_Normal;\n"
882 "uniform sampler2D Texture_Refraction;\n"
883 "uniform sampler2D Texture_Reflection;\n"
884 "\n"
885 "uniform vec4 DistortScaleRefractReflect;\n"
886 "uniform vec4 ScreenScaleRefractReflect;\n"
887 "uniform vec4 ScreenCenterRefractReflect;\n"
888 "uniform vec4 RefractColor;\n"
889 "uniform vec4 ReflectColor;\n"
890 "uniform float ReflectFactor;\n"
891 "uniform float ReflectOffset;\n"
892 "\n"
893 "void main(void)\n"
894 "{\n"
895 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
896 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
897 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
898 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
899 "       // FIXME temporary hack to detect the case that the reflection\n"
900 "       // gets blackened at edges due to leaving the area that contains actual\n"
901 "       // content.\n"
902 "       // Remove this 'ack once we have a better way to stop this thing from\n"
903 "       // 'appening.\n"
904 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
905 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
906 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
907 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
908 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
909 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
910 "}\n"
911 "#endif\n"
912 "#else // !MODE_REFRACTION\n"
913 "\n"
914 "\n"
915 "\n"
916 "\n"
917 "#ifdef MODE_WATER\n"
918 "varying vec2 TexCoord;\n"
919 "varying vec3 EyeVector;\n"
920 "varying vec4 ModelViewProjectionPosition;\n"
921 "#ifdef VERTEX_SHADER\n"
922 "uniform vec3 EyePosition;\n"
923 "uniform mat4 TexMatrix;\n"
924 "\n"
925 "void main(void)\n"
926 "{\n"
927 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
928 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
929 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
930 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
931 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
932 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
933 "       ModelViewProjectionPosition = gl_Position;\n"
934 "}\n"
935 "#endif\n"
936 "\n"
937 "#ifdef FRAGMENT_SHADER\n"
938 "uniform sampler2D Texture_Normal;\n"
939 "uniform sampler2D Texture_Refraction;\n"
940 "uniform sampler2D Texture_Reflection;\n"
941 "\n"
942 "uniform vec4 DistortScaleRefractReflect;\n"
943 "uniform vec4 ScreenScaleRefractReflect;\n"
944 "uniform vec4 ScreenCenterRefractReflect;\n"
945 "uniform vec4 RefractColor;\n"
946 "uniform vec4 ReflectColor;\n"
947 "uniform float ReflectFactor;\n"
948 "uniform float ReflectOffset;\n"
949 "uniform float ClientTime;\n"
950 "#ifdef USENORMALMAPSCROLLBLEND\n"
951 "uniform vec2 NormalmapScrollBlend;\n"
952 "#endif\n"
953 "\n"
954 "void main(void)\n"
955 "{\n"
956 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
957 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
958 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
959 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
960 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
961 "       #ifdef USENORMALMAPSCROLLBLEND\n"
962 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
963 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
964 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
965 "       #else\n"
966 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
967 "       #endif\n"
968 "       // FIXME temporary hack to detect the case that the reflection\n"
969 "       // gets blackened at edges due to leaving the area that contains actual\n"
970 "       // content.\n"
971 "       // Remove this 'ack once we have a better way to stop this thing from\n"
972 "       // 'appening.\n"
973 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
974 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
975 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
976 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
977 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
978 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
979 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
980 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
981 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
982 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
983 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
984 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
985 "       gl_FragColor.a = f1 + 0.5;\n"
986 "}\n"
987 "#endif\n"
988 "#else // !MODE_WATER\n"
989 "\n"
990 "\n"
991 "\n"
992 "\n"
993 "// common definitions between vertex shader and fragment shader:\n"
994 "\n"
995 "varying vec2 TexCoord;\n"
996 "#ifdef USEVERTEXTEXTUREBLEND\n"
997 "varying vec2 TexCoord2;\n"
998 "#endif\n"
999 "#ifdef USELIGHTMAP\n"
1000 "varying vec2 TexCoordLightmap;\n"
1001 "#endif\n"
1002 "\n"
1003 "#ifdef MODE_LIGHTSOURCE\n"
1004 "varying vec3 CubeVector;\n"
1005 "#endif\n"
1006 "\n"
1007 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1008 "varying vec3 LightVector;\n"
1009 "#endif\n"
1010 "\n"
1011 "#ifdef USEEYEVECTOR\n"
1012 "varying vec3 EyeVector;\n"
1013 "#endif\n"
1014 "#ifdef USEFOG\n"
1015 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1016 "#endif\n"
1017 "\n"
1018 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1019 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1020 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1021 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1022 "#endif\n"
1023 "\n"
1024 "#ifdef USEREFLECTION\n"
1025 "varying vec4 ModelViewProjectionPosition;\n"
1026 "#endif\n"
1027 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1028 "uniform vec3 LightPosition;\n"
1029 "varying vec4 ModelViewPosition;\n"
1030 "#endif\n"
1031 "\n"
1032 "#ifdef MODE_LIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1034 "#endif\n"
1035 "uniform vec3 EyePosition;\n"
1036 "#ifdef MODE_LIGHTDIRECTION\n"
1037 "uniform vec3 LightDir;\n"
1038 "#endif\n"
1039 "uniform vec4 FogPlane;\n"
1040 "\n"
1041 "#ifdef USESHADOWMAPORTHO\n"
1042 "varying vec3 ShadowMapTC;\n"
1043 "#endif\n"
1044 "\n"
1045 "\n"
1046 "\n"
1047 "\n"
1048 "\n"
1049 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1050 "\n"
1051 "// fragment shader specific:\n"
1052 "#ifdef FRAGMENT_SHADER\n"
1053 "\n"
1054 "uniform sampler2D Texture_Normal;\n"
1055 "uniform sampler2D Texture_Color;\n"
1056 "uniform sampler2D Texture_Gloss;\n"
1057 "#ifdef USEGLOW\n"
1058 "uniform sampler2D Texture_Glow;\n"
1059 "#endif\n"
1060 "#ifdef USEVERTEXTEXTUREBLEND\n"
1061 "uniform sampler2D Texture_SecondaryNormal;\n"
1062 "uniform sampler2D Texture_SecondaryColor;\n"
1063 "uniform sampler2D Texture_SecondaryGloss;\n"
1064 "#ifdef USEGLOW\n"
1065 "uniform sampler2D Texture_SecondaryGlow;\n"
1066 "#endif\n"
1067 "#endif\n"
1068 "#ifdef USECOLORMAPPING\n"
1069 "uniform sampler2D Texture_Pants;\n"
1070 "uniform sampler2D Texture_Shirt;\n"
1071 "#endif\n"
1072 "#ifdef USEFOG\n"
1073 "#ifdef USEFOGHEIGHTTEXTURE\n"
1074 "uniform sampler2D Texture_FogHeightTexture;\n"
1075 "#endif\n"
1076 "uniform sampler2D Texture_FogMask;\n"
1077 "#endif\n"
1078 "#ifdef USELIGHTMAP\n"
1079 "uniform sampler2D Texture_Lightmap;\n"
1080 "#endif\n"
1081 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1082 "uniform sampler2D Texture_Deluxemap;\n"
1083 "#endif\n"
1084 "#ifdef USEREFLECTION\n"
1085 "uniform sampler2D Texture_Reflection;\n"
1086 "#endif\n"
1087 "\n"
1088 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1089 "uniform sampler2D Texture_ScreenDepth;\n"
1090 "uniform sampler2D Texture_ScreenNormalMap;\n"
1091 "#endif\n"
1092 "#ifdef USEDEFERREDLIGHTMAP\n"
1093 "uniform sampler2D Texture_ScreenDiffuse;\n"
1094 "uniform sampler2D Texture_ScreenSpecular;\n"
1095 "#endif\n"
1096 "\n"
1097 "uniform myhalf3 Color_Pants;\n"
1098 "uniform myhalf3 Color_Shirt;\n"
1099 "uniform myhalf3 FogColor;\n"
1100 "\n"
1101 "#ifdef USEFOG\n"
1102 "uniform float FogRangeRecip;\n"
1103 "uniform float FogPlaneViewDist;\n"
1104 "uniform float FogHeightFade;\n"
1105 "vec3 FogVertex(vec3 surfacecolor)\n"
1106 "{\n"
1107 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1108 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1109 "       float fogfrac;\n"
1110 "#ifdef USEFOGHEIGHTTEXTURE\n"
1111 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1112 "       fogfrac = fogheightpixel.a;\n"
1113 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1114 "#else\n"
1115 "# ifdef USEFOGOUTSIDE\n"
1116 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1117 "# else\n"
1118 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1119 "# endif\n"
1120 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1121 "#endif\n"
1122 "}\n"
1123 "#endif\n"
1124 "\n"
1125 "#ifdef USEOFFSETMAPPING\n"
1126 "uniform float OffsetMapping_Scale;\n"
1127 "vec2 OffsetMapping(vec2 TexCoord)\n"
1128 "{\n"
1129 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1130 "       // 14 sample relief mapping: linear search and then binary search\n"
1131 "       // this basically steps forward a small amount repeatedly until it finds\n"
1132 "       // itself inside solid, then jitters forward and back using decreasing\n"
1133 "       // amounts to find the impact\n"
1134 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1135 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1136 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1137 "       vec3 RT = vec3(TexCoord, 1);\n"
1138 "       OffsetVector *= 0.1;\n"
1139 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1149 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1150 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1151 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1152 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1153 "       return RT.xy;\n"
1154 "#else\n"
1155 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1156 "       // this basically moves forward the full distance, and then backs up based\n"
1157 "       // on height of samples\n"
1158 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1159 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1160 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1161 "       TexCoord += OffsetVector;\n"
1162 "       OffsetVector *= 0.5;\n"
1163 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1164 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1165 "       return TexCoord;\n"
1166 "#endif\n"
1167 "}\n"
1168 "#endif // USEOFFSETMAPPING\n"
1169 "\n"
1170 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1171 "uniform sampler2D Texture_Attenuation;\n"
1172 "uniform samplerCube Texture_Cube;\n"
1173 "#endif\n"
1174 "\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1176 "\n"
1177 "#ifdef USESHADOWMAP2D\n"
1178 "# ifdef USESHADOWSAMPLER\n"
1179 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1180 "# else\n"
1181 "uniform sampler2D Texture_ShadowMap2D;\n"
1182 "# endif\n"
1183 "#endif\n"
1184 "\n"
1185 "#ifdef USESHADOWMAPVSDCT\n"
1186 "uniform samplerCube Texture_CubeProjection;\n"
1187 "#endif\n"
1188 "\n"
1189 "#if defined(USESHADOWMAP2D)\n"
1190 "uniform vec2 ShadowMap_TextureScale;\n"
1191 "uniform vec4 ShadowMap_Parameters;\n"
1192 "#endif\n"
1193 "\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "# ifdef USESHADOWMAPORTHO\n"
1196 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1197 "# else\n"
1198 "#  ifdef USESHADOWMAPVSDCT\n"
1199 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1200 "{\n"
1201 "       vec3 adir = abs(dir);\n"
1202 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1203 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1204 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1205 "}\n"
1206 "#  else\n"
1207 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1208 "{\n"
1209 "       vec3 adir = abs(dir);\n"
1210 "       float ma = adir.z;\n"
1211 "       vec4 proj = vec4(dir, 2.5);\n"
1212 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1213 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1214 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1215 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1216 "}\n"
1217 "#  endif\n"
1218 "# endif\n"
1219 "#endif // defined(USESHADOWMAP2D)\n"
1220 "\n"
1221 "# ifdef USESHADOWMAP2D\n"
1222 "float ShadowMapCompare(vec3 dir)\n"
1223 "{\n"
1224 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1225 "       float f;\n"
1226 "\n"
1227 "#  ifdef USESHADOWSAMPLER\n"
1228 "#    ifdef USESHADOWMAPPCF\n"
1229 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1230 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1231 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1232 "#    else\n"
1233 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1234 "#    endif\n"
1235 "#  else\n"
1236 "#    ifdef USESHADOWMAPPCF\n"
1237 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1238 "#      ifdef GL_ARB_texture_gather\n"
1239 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1240 "#      else\n"
1241 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1242 "#      endif\n"
1243 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1244 "#      if USESHADOWMAPPCF > 1\n"
1245 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1246 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1247 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1248 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1249 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1250 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1251 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1252 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1253 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1254 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1255 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1256 "       locols.yz += group2.ab;\n"
1257 "       hicols.yz += group8.rg;\n"
1258 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1259 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1260 "                               mix(locols, hicols, offset.y);\n"
1261 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1262 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1263 "       f = dot(cols, vec4(1.0/25.0));\n"
1264 "#      else\n"
1265 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1266 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1267 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1268 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1269 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1270 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1271 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1272 "#      endif\n"
1273 "#     else\n"
1274 "#      ifdef GL_EXT_gpu_shader4\n"
1275 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1276 "#      else\n"
1277 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1278 "#      endif\n"
1279 "#      if USESHADOWMAPPCF > 1\n"
1280 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1281 "       center *= ShadowMap_TextureScale;\n"
1282 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1283 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1284 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1285 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1286 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1287 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1288 "#      else\n"
1289 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1290 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1291 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1292 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1293 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1294 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1295 "#      endif\n"
1296 "#     endif\n"
1297 "#    else\n"
1298 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1299 "#    endif\n"
1300 "#  endif\n"
1301 "#  ifdef USESHADOWMAPORTHO\n"
1302 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1303 "#  else\n"
1304 "       return f;\n"
1305 "#  endif\n"
1306 "}\n"
1307 "# endif\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1309 "#endif // FRAGMENT_SHADER\n"
1310 "\n"
1311 "\n"
1312 "\n"
1313 "\n"
1314 "#ifdef MODE_DEFERREDGEOMETRY\n"
1315 "#ifdef VERTEX_SHADER\n"
1316 "uniform mat4 TexMatrix;\n"
1317 "#ifdef USEVERTEXTEXTUREBLEND\n"
1318 "uniform mat4 BackgroundTexMatrix;\n"
1319 "#endif\n"
1320 "uniform mat4 ModelViewMatrix;\n"
1321 "void main(void)\n"
1322 "{\n"
1323 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 "       gl_FrontColor = gl_Color;\n"
1326 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1327 "#endif\n"
1328 "\n"
1329 "       // transform unnormalized eye direction into tangent space\n"
1330 "#ifdef USEOFFSETMAPPING\n"
1331 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1332 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1333 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1334 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1335 "#endif\n"
1336 "\n"
1337 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1338 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1339 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1340 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1341 "}\n"
1342 "#endif // VERTEX_SHADER\n"
1343 "\n"
1344 "#ifdef FRAGMENT_SHADER\n"
1345 "void main(void)\n"
1346 "{\n"
1347 "#ifdef USEOFFSETMAPPING\n"
1348 "       // apply offsetmapping\n"
1349 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1350 "#define TexCoord TexCoordOffset\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEALPHAKILL\n"
1354 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1355 "               discard;\n"
1356 "#endif\n"
1357 "\n"
1358 "#ifdef USEVERTEXTEXTUREBLEND\n"
1359 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1360 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1361 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1362 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1363 "#endif\n"
1364 "\n"
1365 "#ifdef USEVERTEXTEXTUREBLEND\n"
1366 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1367 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1368 "#else\n"
1369 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1370 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1371 "#endif\n"
1372 "\n"
1373 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1374 "}\n"
1375 "#endif // FRAGMENT_SHADER\n"
1376 "#else // !MODE_DEFERREDGEOMETRY\n"
1377 "\n"
1378 "\n"
1379 "\n"
1380 "\n"
1381 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1382 "#ifdef VERTEX_SHADER\n"
1383 "uniform mat4 ModelViewMatrix;\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1387 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1388 "}\n"
1389 "#endif // VERTEX_SHADER\n"
1390 "\n"
1391 "#ifdef FRAGMENT_SHADER\n"
1392 "uniform mat4 ViewToLight;\n"
1393 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1394 "uniform vec2 ScreenToDepth;\n"
1395 "uniform myhalf3 DeferredColor_Ambient;\n"
1396 "uniform myhalf3 DeferredColor_Diffuse;\n"
1397 "#ifdef USESPECULAR\n"
1398 "uniform myhalf3 DeferredColor_Specular;\n"
1399 "uniform myhalf SpecularPower;\n"
1400 "#endif\n"
1401 "uniform myhalf2 PixelToScreenTexCoord;\n"
1402 "void main(void)\n"
1403 "{\n"
1404 "       // calculate viewspace pixel position\n"
1405 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1406 "       vec3 position;\n"
1407 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1408 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1409 "       // decode viewspace pixel normal\n"
1410 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1411 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1412 "       // surfacenormal = pixel normal in viewspace\n"
1413 "       // LightVector = pixel to light in viewspace\n"
1414 "       // CubeVector = position in lightspace\n"
1415 "       // eyevector = pixel to view in viewspace\n"
1416 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1417 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1418 "#ifdef USEDIFFUSE\n"
1419 "       // calculate diffuse shading\n"
1420 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1421 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1422 "#endif\n"
1423 "#ifdef USESPECULAR\n"
1424 "       // calculate directional shading\n"
1425 "       vec3 eyevector = position * -1.0;\n"
1426 "#  ifdef USEEXACTSPECULARMATH\n"
1427 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1428 "#  else\n"
1429 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1430 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1431 "#  endif\n"
1432 "#endif\n"
1433 "\n"
1434 "#if defined(USESHADOWMAP2D)\n"
1435 "       fade *= ShadowMapCompare(CubeVector);\n"
1436 "#endif\n"
1437 "\n"
1438 "#ifdef USEDIFFUSE\n"
1439 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1440 "#else\n"
1441 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1442 "#endif\n"
1443 "#ifdef USESPECULAR\n"
1444 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1445 "#else\n"
1446 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1447 "#endif\n"
1448 "\n"
1449 "# ifdef USECUBEFILTER\n"
1450 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1451 "       gl_FragData[0].rgb *= cubecolor;\n"
1452 "       gl_FragData[1].rgb *= cubecolor;\n"
1453 "# endif\n"
1454 "}\n"
1455 "#endif // FRAGMENT_SHADER\n"
1456 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1457 "\n"
1458 "\n"
1459 "\n"
1460 "\n"
1461 "#ifdef VERTEX_SHADER\n"
1462 "uniform mat4 TexMatrix;\n"
1463 "#ifdef USEVERTEXTEXTUREBLEND\n"
1464 "uniform mat4 BackgroundTexMatrix;\n"
1465 "#endif\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 "uniform mat4 ModelToLight;\n"
1468 "#endif\n"
1469 "#ifdef USESHADOWMAPORTHO\n"
1470 "uniform mat4 ShadowMapMatrix;\n"
1471 "#endif\n"
1472 "void main(void)\n"
1473 "{\n"
1474 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1475 "       gl_FrontColor = gl_Color;\n"
1476 "#endif\n"
1477 "       // copy the surface texcoord\n"
1478 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1479 "#ifdef USEVERTEXTEXTUREBLEND\n"
1480 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1481 "#endif\n"
1482 "#ifdef USELIGHTMAP\n"
1483 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 "       // transform vertex position into light attenuation/cubemap space\n"
1488 "       // (-1 to +1 across the light box)\n"
1489 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1490 "\n"
1491 "# ifdef USEDIFFUSE\n"
1492 "       // transform unnormalized light direction into tangent space\n"
1493 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1494 "       //  normalize it per pixel)\n"
1495 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1496 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1497 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1498 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1499 "# endif\n"
1500 "#endif\n"
1501 "\n"
1502 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1503 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1504 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1505 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1506 "#endif\n"
1507 "\n"
1508 "       // transform unnormalized eye direction into tangent space\n"
1509 "#ifdef USEEYEVECTOR\n"
1510 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1511 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1512 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1513 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1514 "#endif\n"
1515 "\n"
1516 "#ifdef USEFOG\n"
1517 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1518 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1519 "#endif\n"
1520 "\n"
1521 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1522 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1523 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1524 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1525 "#endif\n"
1526 "\n"
1527 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1528 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1529 "\n"
1530 "#ifdef USESHADOWMAPORTHO\n"
1531 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEREFLECTION\n"
1535 "       ModelViewProjectionPosition = gl_Position;\n"
1536 "#endif\n"
1537 "}\n"
1538 "#endif // VERTEX_SHADER\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "#ifdef FRAGMENT_SHADER\n"
1544 "#ifdef USEDEFERREDLIGHTMAP\n"
1545 "uniform myhalf2 PixelToScreenTexCoord;\n"
1546 "uniform myhalf3 DeferredMod_Diffuse;\n"
1547 "uniform myhalf3 DeferredMod_Specular;\n"
1548 "#endif\n"
1549 "uniform myhalf3 Color_Ambient;\n"
1550 "uniform myhalf3 Color_Diffuse;\n"
1551 "uniform myhalf3 Color_Specular;\n"
1552 "uniform myhalf SpecularPower;\n"
1553 "#ifdef USEGLOW\n"
1554 "uniform myhalf3 Color_Glow;\n"
1555 "#endif\n"
1556 "uniform myhalf Alpha;\n"
1557 "#ifdef USEREFLECTION\n"
1558 "uniform vec4 DistortScaleRefractReflect;\n"
1559 "uniform vec4 ScreenScaleRefractReflect;\n"
1560 "uniform vec4 ScreenCenterRefractReflect;\n"
1561 "uniform myhalf4 ReflectColor;\n"
1562 "#endif\n"
1563 "#ifdef USEREFLECTCUBE\n"
1564 "uniform mat4 ModelToReflectCube;\n"
1565 "uniform sampler2D Texture_ReflectMask;\n"
1566 "uniform samplerCube Texture_ReflectCube;\n"
1567 "#endif\n"
1568 "#ifdef MODE_LIGHTDIRECTION\n"
1569 "uniform myhalf3 LightColor;\n"
1570 "#endif\n"
1571 "#ifdef MODE_LIGHTSOURCE\n"
1572 "uniform myhalf3 LightColor;\n"
1573 "#endif\n"
1574 "void main(void)\n"
1575 "{\n"
1576 "#ifdef USEOFFSETMAPPING\n"
1577 "       // apply offsetmapping\n"
1578 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1579 "#define TexCoord TexCoordOffset\n"
1580 "#endif\n"
1581 "\n"
1582 "       // combine the diffuse textures (base, pants, shirt)\n"
1583 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1584 "#ifdef USEALPHAKILL\n"
1585 "       if (color.a < 0.5)\n"
1586 "               discard;\n"
1587 "#endif\n"
1588 "       color.a *= Alpha;\n"
1589 "#ifdef USECOLORMAPPING\n"
1590 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1591 "#endif\n"
1592 "#ifdef USEVERTEXTEXTUREBLEND\n"
1593 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1594 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1595 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1596 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1597 "       color.a = 1.0;\n"
1598 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1599 "#endif\n"
1600 "\n"
1601 "       // get the surface normal\n"
1602 "#ifdef USEVERTEXTEXTUREBLEND\n"
1603 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1604 "#else\n"
1605 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1606 "#endif\n"
1607 "\n"
1608 "       // get the material colors\n"
1609 "       myhalf3 diffusetex = color.rgb;\n"
1610 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1611 "# ifdef USEVERTEXTEXTUREBLEND\n"
1612 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1613 "# else\n"
1614 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1615 "# endif\n"
1616 "#endif\n"
1617 "\n"
1618 "#ifdef USEREFLECTCUBE\n"
1619 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1620 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1621 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1622 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1623 "#endif\n"
1624 "\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "#ifdef MODE_LIGHTSOURCE\n"
1629 "       // light source\n"
1630 "#ifdef USEDIFFUSE\n"
1631 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1632 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1633 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1634 "#ifdef USESPECULAR\n"
1635 "#ifdef USEEXACTSPECULARMATH\n"
1636 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1637 "#else\n"
1638 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1639 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1640 "#endif\n"
1641 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1642 "#endif\n"
1643 "#else\n"
1644 "       color.rgb = diffusetex * Color_Ambient;\n"
1645 "#endif\n"
1646 "       color.rgb *= LightColor;\n"
1647 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1648 "#if defined(USESHADOWMAP2D)\n"
1649 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1650 "#endif\n"
1651 "# ifdef USECUBEFILTER\n"
1652 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1653 "# endif\n"
1654 "#endif // MODE_LIGHTSOURCE\n"
1655 "\n"
1656 "\n"
1657 "\n"
1658 "\n"
1659 "#ifdef MODE_LIGHTDIRECTION\n"
1660 "#define SHADING\n"
1661 "#ifdef USEDIFFUSE\n"
1662 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1663 "#endif\n"
1664 "#define lightcolor LightColor\n"
1665 "#endif // MODE_LIGHTDIRECTION\n"
1666 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1667 "#define SHADING\n"
1668 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1669 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1670 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1671 "       // convert modelspace light vector to tangentspace\n"
1672 "       myhalf3 lightnormal;\n"
1673 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1674 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1675 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1676 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1677 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1678 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1679 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1680 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1681 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1682 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1683 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1684 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1685 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1686 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1687 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1688 "#define SHADING\n"
1689 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1690 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1691 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1692 "#endif\n"
1693 "\n"
1694 "\n"
1695 "\n"
1696 "\n"
1697 "#ifdef MODE_FAKELIGHT\n"
1698 "#define SHADING\n"
1699 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1700 "myhalf3 lightcolor = myhalf3(1.0);\n"
1701 "#endif // MODE_FAKELIGHT\n"
1702 "\n"
1703 "\n"
1704 "\n"
1705 "\n"
1706 "#ifdef MODE_LIGHTMAP\n"
1707 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1708 "#endif // MODE_LIGHTMAP\n"
1709 "#ifdef MODE_VERTEXCOLOR\n"
1710 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1711 "#endif // MODE_VERTEXCOLOR\n"
1712 "#ifdef MODE_FLATCOLOR\n"
1713 "       color.rgb = diffusetex * Color_Ambient;\n"
1714 "#endif // MODE_FLATCOLOR\n"
1715 "\n"
1716 "\n"
1717 "\n"
1718 "\n"
1719 "#ifdef SHADING\n"
1720 "# ifdef USEDIFFUSE\n"
1721 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1722 "#  ifdef USESPECULAR\n"
1723 "#   ifdef USEEXACTSPECULARMATH\n"
1724 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1725 "#   else\n"
1726 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1727 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1728 "#   endif\n"
1729 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1730 "#  else\n"
1731 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1732 "#  endif\n"
1733 "# else\n"
1734 "       color.rgb = diffusetex * Color_Ambient;\n"
1735 "# endif\n"
1736 "#endif\n"
1737 "\n"
1738 "#ifdef USESHADOWMAPORTHO\n"
1739 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1740 "#endif\n"
1741 "\n"
1742 "#ifdef USEDEFERREDLIGHTMAP\n"
1743 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1744 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1745 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef USEGLOW\n"
1749 "#ifdef USEVERTEXTEXTUREBLEND\n"
1750 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1751 "#else\n"
1752 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1753 "#endif\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef USEFOG\n"
1757 "       color.rgb = FogVertex(color.rgb);\n"
1758 "#endif\n"
1759 "\n"
1760 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1761 "#ifdef USEREFLECTION\n"
1762 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1763 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1764 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1765 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1766 "       // FIXME temporary hack to detect the case that the reflection\n"
1767 "       // gets blackened at edges due to leaving the area that contains actual\n"
1768 "       // content.\n"
1769 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1770 "       // 'appening.\n"
1771 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1772 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1773 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1774 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1775 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1776 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1777 "#endif\n"
1778 "\n"
1779 "       gl_FragColor = vec4(color);\n"
1780 "}\n"
1781 "#endif // FRAGMENT_SHADER\n"
1782 "\n"
1783 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1784 "#endif // !MODE_DEFERREDGEOMETRY\n"
1785 "#endif // !MODE_WATER\n"
1786 "#endif // !MODE_REFRACTION\n"
1787 "#endif // !MODE_BLOOMBLUR\n"
1788 "#endif // !MODE_GENERIC\n"
1789 "#endif // !MODE_POSTPROCESS\n"
1790 "#endif // !MODE_SHOWDEPTH\n"
1791 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1792 ;
1793
1794 /*
1795 =========================================================================================================================================================
1796
1797
1798
1799 =========================================================================================================================================================
1800
1801
1802
1803 =========================================================================================================================================================
1804
1805
1806
1807 =========================================================================================================================================================
1808
1809
1810
1811 =========================================================================================================================================================
1812
1813
1814
1815 =========================================================================================================================================================
1816
1817
1818
1819 =========================================================================================================================================================
1820 */
1821
1822 const char *builtincgshaderstring =
1823 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1824 "// written by Forest 'LordHavoc' Hale\n"
1825 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1826 "\n"
1827 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1828 "#if defined(USEREFLECTION)\n"
1829 "#undef USESHADOWMAPORTHO\n"
1830 "#endif\n"
1831 "\n"
1832 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1833 "# define USEFOG\n"
1834 "#endif\n"
1835 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1836 "#define USELIGHTMAP\n"
1837 "#endif\n"
1838 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1839 "#define USEEYEVECTOR\n"
1840 "#endif\n"
1841 "\n"
1842 "#ifdef FRAGMENT_SHADER\n"
1843 "#ifdef HLSL\n"
1844 "//#undef USESHADOWMAPPCF\n"
1845 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1846 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1847 "#else\n"
1848 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1849 "#endif\n"
1850 "#endif\n"
1851 "\n"
1852 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1853 "#ifdef VERTEX_SHADER\n"
1854 "void main\n"
1855 "(\n"
1856 "float4 gl_Vertex : POSITION,\n"
1857 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1858 "out float4 gl_Position : POSITION,\n"
1859 "out float Depth : TEXCOORD0\n"
1860 ")\n"
1861 "{\n"
1862 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1863 "       Depth = gl_Position.z;\n"
1864 "}\n"
1865 "#endif\n"
1866 "\n"
1867 "#ifdef FRAGMENT_SHADER\n"
1868 "void main\n"
1869 "(\n"
1870 "float Depth : TEXCOORD0,\n"
1871 "out float4 gl_FragColor : COLOR\n"
1872 ")\n"
1873 "{\n"
1874 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1875 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1876 "       temp.yz -= floor(temp.yz);\n"
1877 "       gl_FragColor = temp;\n"
1878 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1879 "}\n"
1880 "#endif\n"
1881 "#else // !MODE_DEPTH_ORSHADOW\n"
1882 "\n"
1883 "\n"
1884 "\n"
1885 "\n"
1886 "#ifdef MODE_SHOWDEPTH\n"
1887 "#ifdef VERTEX_SHADER\n"
1888 "void main\n"
1889 "(\n"
1890 "float4 gl_Vertex : POSITION,\n"
1891 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1892 "out float4 gl_Position : POSITION,\n"
1893 "out float4 gl_FrontColor : COLOR0\n"
1894 ")\n"
1895 "{\n"
1896 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1897 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1898 "}\n"
1899 "#endif\n"
1900 "\n"
1901 "#ifdef FRAGMENT_SHADER\n"
1902 "void main\n"
1903 "(\n"
1904 "float4 gl_FrontColor : COLOR0,\n"
1905 "out float4 gl_FragColor : COLOR\n"
1906 ")\n"
1907 "{\n"
1908 "       gl_FragColor = gl_FrontColor;\n"
1909 "}\n"
1910 "#endif\n"
1911 "#else // !MODE_SHOWDEPTH\n"
1912 "\n"
1913 "\n"
1914 "\n"
1915 "\n"
1916 "#ifdef MODE_POSTPROCESS\n"
1917 "\n"
1918 "#ifdef VERTEX_SHADER\n"
1919 "void main\n"
1920 "(\n"
1921 "float4 gl_Vertex : POSITION,\n"
1922 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1923 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1924 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1925 "out float4 gl_Position : POSITION,\n"
1926 "out float2 TexCoord1 : TEXCOORD0,\n"
1927 "out float2 TexCoord2 : TEXCOORD1\n"
1928 ")\n"
1929 "{\n"
1930 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1931 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1932 "#ifdef USEBLOOM\n"
1933 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1934 "#endif\n"
1935 "}\n"
1936 "#endif\n"
1937 "\n"
1938 "#ifdef FRAGMENT_SHADER\n"
1939 "void main\n"
1940 "(\n"
1941 "float2 TexCoord1 : TEXCOORD0,\n"
1942 "float2 TexCoord2 : TEXCOORD1,\n"
1943 "uniform sampler Texture_First : register(s0),\n"
1944 "#ifdef USEBLOOM\n"
1945 "uniform sampler Texture_Second : register(s1),\n"
1946 "#endif\n"
1947 "#ifdef USEGAMMARAMPS\n"
1948 "uniform sampler Texture_GammaRamps : register(s2),\n"
1949 "#endif\n"
1950 "#ifdef USESATURATION\n"
1951 "uniform float Saturation : register(c30),\n"
1952 "#endif\n"
1953 "#ifdef USEVIEWTINT\n"
1954 "uniform float4 ViewTintColor : register(c41),\n"
1955 "#endif\n"
1956 "uniform float4 UserVec1 : register(c37),\n"
1957 "uniform float4 UserVec2 : register(c38),\n"
1958 "uniform float4 UserVec3 : register(c39),\n"
1959 "uniform float4 UserVec4 : register(c40),\n"
1960 "uniform float ClientTime : register(c2),\n"
1961 "uniform float2 PixelSize : register(c25),\n"
1962 "uniform float4 BloomColorSubtract : register(c43),\n"
1963 "out float4 gl_FragColor : COLOR\n"
1964 ")\n"
1965 "{\n"
1966 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1967 "#ifdef USEBLOOM\n"
1968 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1969 "#endif\n"
1970 "#ifdef USEVIEWTINT\n"
1971 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef USEPOSTPROCESSING\n"
1975 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1976 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1977 "       float sobel = 1.0;\n"
1978 "       // float2 ts = textureSize(Texture_First, 0);\n"
1979 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1980 "       float2 px = PixelSize;\n"
1981 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1982 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1983 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1984 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1985 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1986 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1987 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1988 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1989 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1992 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1993 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1994 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1995 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1996 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1997 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1998 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1999 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2000 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2001 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2002 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2003 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2004 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2005 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2006 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2007 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2008 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2009 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2010 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2011 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2012 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2013 "#endif\n"
2014 "\n"
2015 "#ifdef USESATURATION\n"
2016 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2017 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2018 "       // 'vampire sight' effect, wheres red is compensated\n"
2019 "       #ifdef SATURATION_REDCOMPENSATE\n"
2020 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2021 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2022 "               gl_FragColor.r += r;\n"
2023 "       #else\n"
2024 "               // normal desaturation\n"
2025 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2026 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2027 "       #endif\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEGAMMARAMPS\n"
2031 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2032 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2033 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2034 "#endif\n"
2035 "}\n"
2036 "#endif\n"
2037 "#else // !MODE_POSTPROCESS\n"
2038 "\n"
2039 "\n"
2040 "\n"
2041 "\n"
2042 "#ifdef MODE_GENERIC\n"
2043 "#ifdef VERTEX_SHADER\n"
2044 "void main\n"
2045 "(\n"
2046 "float4 gl_Vertex : POSITION,\n"
2047 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2048 "float4 gl_Color : COLOR0,\n"
2049 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2050 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2051 "out float4 gl_Position : POSITION,\n"
2052 "#ifdef USEDIFFUSE\n"
2053 "out float2 TexCoord1 : TEXCOORD0,\n"
2054 "#endif\n"
2055 "#ifdef USESPECULAR\n"
2056 "out float2 TexCoord2 : TEXCOORD1,\n"
2057 "#endif\n"
2058 "out float4 gl_FrontColor : COLOR\n"
2059 ")\n"
2060 "{\n"
2061 "#ifdef HLSL\n"
2062 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2063 "#else\n"
2064 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2065 "#endif\n"
2066 "#ifdef USEDIFFUSE\n"
2067 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2068 "#endif\n"
2069 "#ifdef USESPECULAR\n"
2070 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2071 "#endif\n"
2072 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2073 "}\n"
2074 "#endif\n"
2075 "\n"
2076 "#ifdef FRAGMENT_SHADER\n"
2077 "\n"
2078 "void main\n"
2079 "(\n"
2080 "float4 gl_FrontColor : COLOR0,\n"
2081 "float2 TexCoord1 : TEXCOORD0,\n"
2082 "float2 TexCoord2 : TEXCOORD1,\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "uniform sampler Texture_First : register(s0),\n"
2085 "#endif\n"
2086 "#ifdef USESPECULAR\n"
2087 "uniform sampler Texture_Second : register(s1),\n"
2088 "#endif\n"
2089 "out float4 gl_FragColor : COLOR\n"
2090 ")\n"
2091 "{\n"
2092 "       gl_FragColor = gl_FrontColor;\n"
2093 "#ifdef USEDIFFUSE\n"
2094 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2095 "#endif\n"
2096 "\n"
2097 "#ifdef USESPECULAR\n"
2098 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2099 "# ifdef USECOLORMAPPING\n"
2100 "       gl_FragColor *= tex2;\n"
2101 "# endif\n"
2102 "# ifdef USEGLOW\n"
2103 "       gl_FragColor += tex2;\n"
2104 "# endif\n"
2105 "# ifdef USEVERTEXTEXTUREBLEND\n"
2106 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2107 "# endif\n"
2108 "#endif\n"
2109 "}\n"
2110 "#endif\n"
2111 "#else // !MODE_GENERIC\n"
2112 "\n"
2113 "\n"
2114 "\n"
2115 "\n"
2116 "#ifdef MODE_BLOOMBLUR\n"
2117 "#ifdef VERTEX_SHADER\n"
2118 "void main\n"
2119 "(\n"
2120 "float4 gl_Vertex : POSITION,\n"
2121 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2122 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2123 "out float4 gl_Position : POSITION,\n"
2124 "out float2 TexCoord : TEXCOORD0\n"
2125 ")\n"
2126 "{\n"
2127 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2128 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2129 "}\n"
2130 "#endif\n"
2131 "\n"
2132 "#ifdef FRAGMENT_SHADER\n"
2133 "\n"
2134 "void main\n"
2135 "(\n"
2136 "float2 TexCoord : TEXCOORD0,\n"
2137 "uniform sampler Texture_First : register(s0),\n"
2138 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2139 "out float4 gl_FragColor : COLOR\n"
2140 ")\n"
2141 "{\n"
2142 "       int i;\n"
2143 "       float2 tc = TexCoord;\n"
2144 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2145 "       tc += BloomBlur_Parameters.xy;\n"
2146 "       for (i = 1;i < SAMPLES;i++)\n"
2147 "       {\n"
2148 "               color += tex2D(Texture_First, tc).rgb;\n"
2149 "               tc += BloomBlur_Parameters.xy;\n"
2150 "       }\n"
2151 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2152 "}\n"
2153 "#endif\n"
2154 "#else // !MODE_BLOOMBLUR\n"
2155 "#ifdef MODE_REFRACTION\n"
2156 "#ifdef VERTEX_SHADER\n"
2157 "void main\n"
2158 "(\n"
2159 "float4 gl_Vertex : POSITION,\n"
2160 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2161 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2162 "uniform float4x4 TexMatrix : register(c0),\n"
2163 "uniform float3 EyePosition : register(c24),\n"
2164 "out float4 gl_Position : POSITION,\n"
2165 "out float2 TexCoord : TEXCOORD0,\n"
2166 "out float3 EyeVector : TEXCOORD1,\n"
2167 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2168 ")\n"
2169 "{\n"
2170 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2171 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2172 "       ModelViewProjectionPosition = gl_Position;\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "void main\n"
2178 "(\n"
2179 "float2 TexCoord : TEXCOORD0,\n"
2180 "float3 EyeVector : TEXCOORD1,\n"
2181 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2182 "uniform sampler Texture_Normal : register(s0),\n"
2183 "uniform sampler Texture_Refraction : register(s3),\n"
2184 "uniform sampler Texture_Reflection : register(s7),\n"
2185 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2186 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2187 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2188 "uniform float4 RefractColor : register(c29),\n"
2189 "out float4 gl_FragColor : COLOR\n"
2190 ")\n"
2191 "{\n"
2192 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2193 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2194 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2195 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2196 "       // FIXME temporary hack to detect the case that the reflection\n"
2197 "       // gets blackened at edges due to leaving the area that contains actual\n"
2198 "       // content.\n"
2199 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2200 "       // 'appening.\n"
2201 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2202 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2203 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2204 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2205 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2206 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2207 "}\n"
2208 "#endif\n"
2209 "#else // !MODE_REFRACTION\n"
2210 "\n"
2211 "\n"
2212 "\n"
2213 "\n"
2214 "#ifdef MODE_WATER\n"
2215 "#ifdef VERTEX_SHADER\n"
2216 "\n"
2217 "void main\n"
2218 "(\n"
2219 "float4 gl_Vertex : POSITION,\n"
2220 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2221 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2222 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2223 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2224 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2225 "uniform float4x4 TexMatrix : register(c0),\n"
2226 "uniform float3 EyePosition : register(c24),\n"
2227 "out float4 gl_Position : POSITION,\n"
2228 "out float2 TexCoord : TEXCOORD0,\n"
2229 "out float3 EyeVector : TEXCOORD1,\n"
2230 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2231 ")\n"
2232 "{\n"
2233 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2234 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2235 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2236 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2237 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2238 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2239 "       ModelViewProjectionPosition = gl_Position;\n"
2240 "}\n"
2241 "#endif\n"
2242 "\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2244 "void main\n"
2245 "(\n"
2246 "float2 TexCoord : TEXCOORD0,\n"
2247 "float3 EyeVector : TEXCOORD1,\n"
2248 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2249 "uniform sampler Texture_Normal : register(s0),\n"
2250 "uniform sampler Texture_Refraction : register(s3),\n"
2251 "uniform sampler Texture_Reflection : register(s7),\n"
2252 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2253 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2254 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2255 "uniform float4 RefractColor : register(c29),\n"
2256 "uniform float4 ReflectColor : register(c26),\n"
2257 "uniform float ReflectFactor : register(c27),\n"
2258 "uniform float ReflectOffset : register(c28),\n"
2259 "out float4 gl_FragColor : COLOR\n"
2260 ")\n"
2261 "{\n"
2262 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2263 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2264 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2265 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2266 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2267 "       // FIXME temporary hack to detect the case that the reflection\n"
2268 "       // gets blackened at edges due to leaving the area that contains actual\n"
2269 "       // content.\n"
2270 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2271 "       // 'appening.\n"
2272 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2273 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2274 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2275 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2276 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2277 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2278 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2279 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2280 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2281 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2282 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2283 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2284 "}\n"
2285 "#endif\n"
2286 "#else // !MODE_WATER\n"
2287 "\n"
2288 "\n"
2289 "\n"
2290 "\n"
2291 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2292 "\n"
2293 "// fragment shader specific:\n"
2294 "#ifdef FRAGMENT_SHADER\n"
2295 "\n"
2296 "#ifdef USEFOG\n"
2297 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2298 "{\n"
2299 "       float fogfrac;\n"
2300 "#ifdef USEFOGHEIGHTTEXTURE\n"
2301 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2302 "       fogfrac = fogheightpixel.a;\n"
2303 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2304 "#else\n"
2305 "# ifdef USEFOGOUTSIDE\n"
2306 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2307 "# else\n"
2308 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2309 "# endif\n"
2310 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2311 "#endif\n"
2312 "}\n"
2313 "#endif\n"
2314 "\n"
2315 "#ifdef USEOFFSETMAPPING\n"
2316 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2317 "{\n"
2318 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2319 "       // 14 sample relief mapping: linear search and then binary search\n"
2320 "       // this basically steps forward a small amount repeatedly until it finds\n"
2321 "       // itself inside solid, then jitters forward and back using decreasing\n"
2322 "       // amounts to find the impact\n"
2323 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2324 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2325 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2326 "       float3 RT = float3(TexCoord, 1);\n"
2327 "       OffsetVector *= 0.1;\n"
2328 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2334 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2335 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2336 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2337 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2338 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2339 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2340 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2341 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2342 "       return RT.xy;\n"
2343 "#else\n"
2344 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2345 "       // this basically moves forward the full distance, and then backs up based\n"
2346 "       // on height of samples\n"
2347 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2348 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2349 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2350 "       TexCoord += OffsetVector;\n"
2351 "       OffsetVector *= 0.333;\n"
2352 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2353 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2354 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2355 "       return TexCoord;\n"
2356 "#endif\n"
2357 "}\n"
2358 "#endif // USEOFFSETMAPPING\n"
2359 "\n"
2360 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2361 "#if defined(USESHADOWMAP2D)\n"
2362 "# ifdef USESHADOWMAPORTHO\n"
2363 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2364 "# else\n"
2365 "#  ifdef USESHADOWMAPVSDCT\n"
2366 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2367 "{\n"
2368 "       float3 adir = abs(dir);\n"
2369 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2370 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2371 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2372 "}\n"
2373 "#  else\n"
2374 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2375 "{\n"
2376 "       float3 adir = abs(dir);\n"
2377 "       float ma = adir.z;\n"
2378 "       float4 proj = float4(dir, 2.5);\n"
2379 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2380 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2381 "#ifdef HLSL\n"
2382 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2383 "#else\n"
2384 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2385 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2386 "#endif\n"
2387 "}\n"
2388 "#  endif\n"
2389 "# endif\n"
2390 "#endif // defined(USESHADOWMAP2D)\n"
2391 "\n"
2392 "# ifdef USESHADOWMAP2D\n"
2393 "#ifdef USESHADOWMAPVSDCT\n"
2394 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2395 "#else\n"
2396 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2397 "#endif\n"
2398 "{\n"
2399 "#ifdef USESHADOWMAPVSDCT\n"
2400 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2401 "#else\n"
2402 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2403 "#endif\n"
2404 "       float f;\n"
2405 "\n"
2406 "#  ifdef USESHADOWSAMPLER\n"
2407 "#    ifdef USESHADOWMAPPCF\n"
2408 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2409 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2410 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2411 "#    else\n"
2412 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2413 "#    endif\n"
2414 "#  else\n"
2415 "#    ifdef USESHADOWMAPPCF\n"
2416 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2417 "#      ifdef GL_ARB_texture_gather\n"
2418 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2419 "#      else\n"
2420 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2421 "#      endif\n"
2422 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2423 "#      if USESHADOWMAPPCF > 1\n"
2424 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2425 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2426 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2427 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2428 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2429 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2430 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2431 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2432 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2433 "       float4 locols = float4(group1.ab, group3.ab);\n"
2434 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2435 "       locols.yz += group2.ab;\n"
2436 "       hicols.yz += group8.rg;\n"
2437 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2438 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2439 "                               lerp(locols, hicols, offset.y);\n"
2440 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2441 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2442 "       f = dot(cols, float4(1.0/25.0));\n"
2443 "#      else\n"
2444 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2445 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2446 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2447 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2448 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2449 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2450 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2451 "#      endif\n"
2452 "#     else\n"
2453 "#      ifdef GL_EXT_gpu_shader4\n"
2454 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2455 "#      else\n"
2456 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2457 "#      endif\n"
2458 "#      if USESHADOWMAPPCF > 1\n"
2459 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2460 "       center *= ShadowMap_TextureScale;\n"
2461 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2462 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2463 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2464 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2465 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2466 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2467 "#      else\n"
2468 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2469 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2470 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2471 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2472 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2473 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2474 "#      endif\n"
2475 "#     endif\n"
2476 "#    else\n"
2477 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2478 "#    endif\n"
2479 "#  endif\n"
2480 "#  ifdef USESHADOWMAPORTHO\n"
2481 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2482 "#  else\n"
2483 "       return f;\n"
2484 "#  endif\n"
2485 "}\n"
2486 "# endif\n"
2487 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2488 "#endif // FRAGMENT_SHADER\n"
2489 "\n"
2490 "\n"
2491 "\n"
2492 "\n"
2493 "#ifdef MODE_DEFERREDGEOMETRY\n"
2494 "#ifdef VERTEX_SHADER\n"
2495 "void main\n"
2496 "(\n"
2497 "float4 gl_Vertex : POSITION,\n"
2498 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2499 "#ifdef USEVERTEXTEXTUREBLEND\n"
2500 "float4 gl_Color : COLOR0,\n"
2501 "#endif\n"
2502 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2503 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2504 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2505 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2506 "uniform float4x4 TexMatrix : register(c0),\n"
2507 "#ifdef USEVERTEXTEXTUREBLEND\n"
2508 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2509 "#endif\n"
2510 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2511 "#ifdef USEOFFSETMAPPING\n"
2512 "uniform float3 EyePosition : register(c24),\n"
2513 "#endif\n"
2514 "out float4 gl_Position : POSITION,\n"
2515 "#ifdef USEVERTEXTEXTUREBLEND\n"
2516 "out float4 gl_FrontColor : COLOR,\n"
2517 "#endif\n"
2518 "out float4 TexCoordBoth : TEXCOORD0,\n"
2519 "#ifdef USEOFFSETMAPPING\n"
2520 "out float3 EyeVector : TEXCOORD2,\n"
2521 "#endif\n"
2522 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2523 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2524 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2525 ")\n"
2526 "{\n"
2527 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2528 "#ifdef USEVERTEXTEXTUREBLEND\n"
2529 "#ifdef HLSL\n"
2530 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2531 "#else\n"
2532 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2533 "#endif\n"
2534 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2535 "#endif\n"
2536 "\n"
2537 "       // transform unnormalized eye direction into tangent space\n"
2538 "#ifdef USEOFFSETMAPPING\n"
2539 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2540 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2541 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2542 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2543 "#endif\n"
2544 "\n"
2545 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2546 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2547 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2548 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2549 "       VectorR.w = gl_Position.z;\n"
2550 "}\n"
2551 "#endif // VERTEX_SHADER\n"
2552 "\n"
2553 "#ifdef FRAGMENT_SHADER\n"
2554 "void main\n"
2555 "(\n"
2556 "float4 TexCoordBoth : TEXCOORD0,\n"
2557 "float3 EyeVector : TEXCOORD2,\n"
2558 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2559 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2560 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2561 "uniform sampler Texture_Normal : register(s0),\n"
2562 "#ifdef USEALPHAKILL\n"
2563 "uniform sampler Texture_Color : register(s1),\n"
2564 "#endif\n"
2565 "uniform sampler Texture_Gloss : register(s2),\n"
2566 "#ifdef USEVERTEXTEXTUREBLEND\n"
2567 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2568 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2569 "#endif\n"
2570 "#ifdef USEOFFSETMAPPING\n"
2571 "uniform float OffsetMapping_Scale : register(c24),\n"
2572 "#endif\n"
2573 "uniform half SpecularPower : register(c36),\n"
2574 "#ifdef HLSL\n"
2575 "out float4 gl_FragData0 : COLOR0,\n"
2576 "out float4 gl_FragData1 : COLOR1\n"
2577 "#else\n"
2578 "out float4 gl_FragColor : COLOR\n"
2579 "#endif\n"
2580 ")\n"
2581 "{\n"
2582 "       float2 TexCoord = TexCoordBoth.xy;\n"
2583 "#ifdef USEOFFSETMAPPING\n"
2584 "       // apply offsetmapping\n"
2585 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2586 "#define TexCoord TexCoordOffset\n"
2587 "#endif\n"
2588 "\n"
2589 "#ifdef USEALPHAKILL\n"
2590 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2591 "               discard;\n"
2592 "#endif\n"
2593 "\n"
2594 "#ifdef USEVERTEXTEXTUREBLEND\n"
2595 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2596 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2597 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2598 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2599 "#endif\n"
2600 "\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2603 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2604 "#else\n"
2605 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2606 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2607 "#endif\n"
2608 "\n"
2609 "#ifdef HLSL\n"
2610 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2611 "       float Depth = VectorR.w / 256.0;\n"
2612 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2613 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2614 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2615 "       gl_FragData1 = depthcolor;\n"
2616 "#else\n"
2617 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2618 "#endif\n"
2619 "}\n"
2620 "#endif // FRAGMENT_SHADER\n"
2621 "#else // !MODE_DEFERREDGEOMETRY\n"
2622 "\n"
2623 "\n"
2624 "\n"
2625 "\n"
2626 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2627 "#ifdef VERTEX_SHADER\n"
2628 "void main\n"
2629 "(\n"
2630 "float4 gl_Vertex : POSITION,\n"
2631 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2632 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2633 "out float4 gl_Position : POSITION,\n"
2634 "out float4 ModelViewPosition : TEXCOORD0\n"
2635 ")\n"
2636 "{\n"
2637 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2638 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2639 "}\n"
2640 "#endif // VERTEX_SHADER\n"
2641 "\n"
2642 "#ifdef FRAGMENT_SHADER\n"
2643 "void main\n"
2644 "(\n"
2645 "#ifdef HLSL\n"
2646 "float2 Pixel : VPOS,\n"
2647 "#else\n"
2648 "float2 Pixel : WPOS,\n"
2649 "#endif\n"
2650 "float4 ModelViewPosition : TEXCOORD0,\n"
2651 "uniform float4x4 ViewToLight : register(c44),\n"
2652 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2653 "uniform float3 LightPosition : register(c23),\n"
2654 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2655 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2656 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2657 "#ifdef USESPECULAR\n"
2658 "uniform half3 DeferredColor_Specular : register(c11),\n"
2659 "uniform half SpecularPower : register(c36),\n"
2660 "#endif\n"
2661 "uniform sampler Texture_Attenuation : register(s9),\n"
2662 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2663 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2664 "\n"
2665 "#ifdef USECUBEFILTER\n"
2666 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2667 "#endif\n"
2668 "\n"
2669 "#ifdef USESHADOWMAP2D\n"
2670 "# ifdef USESHADOWSAMPLER\n"
2671 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2672 "# else\n"
2673 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2674 "# endif\n"
2675 "#endif\n"
2676 "\n"
2677 "#ifdef USESHADOWMAPVSDCT\n"
2678 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2679 "#endif\n"
2680 "\n"
2681 "#if defined(USESHADOWMAP2D)\n"
2682 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2683 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2684 "#endif\n"
2685 "\n"
2686 "out float4 gl_FragData0 : COLOR0,\n"
2687 "out float4 gl_FragData1 : COLOR1\n"
2688 ")\n"
2689 "{\n"
2690 "       // calculate viewspace pixel position\n"
2691 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2692 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2693 "       float3 position;\n"
2694 "#ifdef HLSL\n"
2695 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2696 "#else\n"
2697 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2698 "#endif\n"
2699 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2700 "       // decode viewspace pixel normal\n"
2701 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2702 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2703 "       // surfacenormal = pixel normal in viewspace\n"
2704 "       // LightVector = pixel to light in viewspace\n"
2705 "       // CubeVector = position in lightspace\n"
2706 "       // eyevector = pixel to view in viewspace\n"
2707 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2708 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2709 "#ifdef USEDIFFUSE\n"
2710 "       // calculate diffuse shading\n"
2711 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2712 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2713 "#endif\n"
2714 "#ifdef USESPECULAR\n"
2715 "       // calculate directional shading\n"
2716 "       float3 eyevector = position * -1.0;\n"
2717 "#  ifdef USEEXACTSPECULARMATH\n"
2718 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2719 "#  else\n"
2720 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2721 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2722 "#  endif\n"
2723 "#endif\n"
2724 "\n"
2725 "#if defined(USESHADOWMAP2D)\n"
2726 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2727 "#ifdef USESHADOWMAPVSDCT\n"
2728 ", Texture_CubeProjection\n"
2729 "#endif\n"
2730 "       ));\n"
2731 "#endif\n"
2732 "\n"
2733 "#ifdef USEDIFFUSE\n"
2734 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2735 "#else\n"
2736 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2737 "#endif\n"
2738 "#ifdef USESPECULAR\n"
2739 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2740 "#else\n"
2741 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2742 "#endif\n"
2743 "\n"
2744 "# ifdef USECUBEFILTER\n"
2745 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2746 "       gl_FragData0.rgb *= cubecolor;\n"
2747 "       gl_FragData1.rgb *= cubecolor;\n"
2748 "# endif\n"
2749 "}\n"
2750 "#endif // FRAGMENT_SHADER\n"
2751 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2752 "\n"
2753 "\n"
2754 "\n"
2755 "\n"
2756 "#ifdef VERTEX_SHADER\n"
2757 "void main\n"
2758 "(\n"
2759 "float4 gl_Vertex : POSITION,\n"
2760 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2761 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2762 "float4 gl_Color : COLOR0,\n"
2763 "#endif\n"
2764 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2765 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2766 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2767 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2768 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2769 "\n"
2770 "uniform float3 EyePosition : register(c24),\n"
2771 "uniform float4x4 TexMatrix : register(c0),\n"
2772 "#ifdef USEVERTEXTEXTUREBLEND\n"
2773 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2774 "#endif\n"
2775 "#ifdef MODE_LIGHTSOURCE\n"
2776 "uniform float4x4 ModelToLight : register(c20),\n"
2777 "#endif\n"
2778 "#ifdef MODE_LIGHTSOURCE\n"
2779 "uniform float3 LightPosition : register(c27),\n"
2780 "#endif\n"
2781 "#ifdef MODE_LIGHTDIRECTION\n"
2782 "uniform float3 LightDir : register(c26),\n"
2783 "#endif\n"
2784 "uniform float4 FogPlane : register(c25),\n"
2785 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2786 "uniform float3 LightPosition : register(c27),\n"
2787 "#endif\n"
2788 "#ifdef USESHADOWMAPORTHO\n"
2789 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2790 "#endif\n"
2791 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2792 "out float4 gl_FrontColor : COLOR,\n"
2793 "#endif\n"
2794 "out float4 TexCoordBoth : TEXCOORD0,\n"
2795 "#ifdef USELIGHTMAP\n"
2796 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2797 "#endif\n"
2798 "#ifdef USEEYEVECTOR\n"
2799 "out float3 EyeVector : TEXCOORD2,\n"
2800 "#endif\n"
2801 "#ifdef USEREFLECTION\n"
2802 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2803 "#endif\n"
2804 "#ifdef USEFOG\n"
2805 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2806 "#endif\n"
2807 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2808 "out float3 LightVector : TEXCOORD1,\n"
2809 "#endif\n"
2810 "#ifdef MODE_LIGHTSOURCE\n"
2811 "out float3 CubeVector : TEXCOORD3,\n"
2812 "#endif\n"
2813 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2814 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2815 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2816 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2817 "#endif\n"
2818 "#ifdef USESHADOWMAPORTHO\n"
2819 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2820 "#endif\n"
2821 "out float4 gl_Position : POSITION\n"
2822 ")\n"
2823 "{\n"
2824 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2825 "#ifdef HLSL\n"
2826 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2827 "#else\n"
2828 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2829 "#endif\n"
2830 "#endif\n"
2831 "       // copy the surface texcoord\n"
2832 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2833 "#ifdef USEVERTEXTEXTUREBLEND\n"
2834 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2835 "#endif\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2838 "#endif\n"
2839 "\n"
2840 "#ifdef MODE_LIGHTSOURCE\n"
2841 "       // transform vertex position into light attenuation/cubemap space\n"
2842 "       // (-1 to +1 across the light box)\n"
2843 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2844 "\n"
2845 "# ifdef USEDIFFUSE\n"
2846 "       // transform unnormalized light direction into tangent space\n"
2847 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2848 "       //  normalize it per pixel)\n"
2849 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2850 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2851 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2852 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2853 "# endif\n"
2854 "#endif\n"
2855 "\n"
2856 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2857 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2858 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2859 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2860 "#endif\n"
2861 "\n"
2862 "       // transform unnormalized eye direction into tangent space\n"
2863 "#ifdef USEEYEVECTOR\n"
2864 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2865 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2866 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2867 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USEFOG\n"
2871 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2872 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2873 "#endif\n"
2874 "\n"
2875 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2876 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2877 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2878 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2879 "#endif\n"
2880 "\n"
2881 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2882 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2883 "\n"
2884 "#ifdef USESHADOWMAPORTHO\n"
2885 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2886 "#endif\n"
2887 "\n"
2888 "#ifdef USEREFLECTION\n"
2889 "       ModelViewProjectionPosition = gl_Position;\n"
2890 "#endif\n"
2891 "}\n"
2892 "#endif // VERTEX_SHADER\n"
2893 "\n"
2894 "\n"
2895 "\n"
2896 "\n"
2897 "#ifdef FRAGMENT_SHADER\n"
2898 "void main\n"
2899 "(\n"
2900 "#ifdef USEDEFERREDLIGHTMAP\n"
2901 "#ifdef HLSL\n"
2902 "float2 Pixel : VPOS,\n"
2903 "#else\n"
2904 "float2 Pixel : WPOS,\n"
2905 "#endif\n"
2906 "#endif\n"
2907 "float4 gl_FrontColor : COLOR,\n"
2908 "float4 TexCoordBoth : TEXCOORD0,\n"
2909 "#ifdef USELIGHTMAP\n"
2910 "float2 TexCoordLightmap : TEXCOORD1,\n"
2911 "#endif\n"
2912 "#ifdef USEEYEVECTOR\n"
2913 "float3 EyeVector : TEXCOORD2,\n"
2914 "#endif\n"
2915 "#ifdef USEREFLECTION\n"
2916 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2917 "#endif\n"
2918 "#ifdef USEFOG\n"
2919 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2920 "#endif\n"
2921 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2922 "float3 LightVector : TEXCOORD1,\n"
2923 "#endif\n"
2924 "#ifdef MODE_LIGHTSOURCE\n"
2925 "float3 CubeVector : TEXCOORD3,\n"
2926 "#endif\n"
2927 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2928 "float4 ModelViewPosition : TEXCOORD0,\n"
2929 "#endif\n"
2930 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2931 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2932 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2933 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2934 "#endif\n"
2935 "#ifdef USESHADOWMAPORTHO\n"
2936 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2937 "#endif\n"
2938 "\n"
2939 "uniform sampler Texture_Normal : register(s0),\n"
2940 "uniform sampler Texture_Color : register(s1),\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "uniform sampler Texture_Gloss : register(s2),\n"
2943 "#endif\n"
2944 "#ifdef USEGLOW\n"
2945 "uniform sampler Texture_Glow : register(s3),\n"
2946 "#endif\n"
2947 "#ifdef USEVERTEXTEXTUREBLEND\n"
2948 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2949 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2951 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2952 "#endif\n"
2953 "#ifdef USEGLOW\n"
2954 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2955 "#endif\n"
2956 "#endif\n"
2957 "#ifdef USECOLORMAPPING\n"
2958 "uniform sampler Texture_Pants : register(s4),\n"
2959 "uniform sampler Texture_Shirt : register(s7),\n"
2960 "#endif\n"
2961 "#ifdef USEFOG\n"
2962 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2963 "uniform sampler Texture_FogMask : register(s8),\n"
2964 "#endif\n"
2965 "#ifdef USELIGHTMAP\n"
2966 "uniform sampler Texture_Lightmap : register(s9),\n"
2967 "#endif\n"
2968 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2969 "uniform sampler Texture_Deluxemap : register(s10),\n"
2970 "#endif\n"
2971 "#ifdef USEREFLECTION\n"
2972 "uniform sampler Texture_Reflection : register(s7),\n"
2973 "#endif\n"
2974 "\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2977 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2978 "#endif\n"
2979 "#ifdef USEDEFERREDLIGHTMAP\n"
2980 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2981 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2982 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2983 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef USECOLORMAPPING\n"
2987 "uniform half3 Color_Pants : register(c7),\n"
2988 "uniform half3 Color_Shirt : register(c8),\n"
2989 "#endif\n"
2990 "#ifdef USEFOG\n"
2991 "uniform float3 FogColor : register(c16),\n"
2992 "uniform float FogRangeRecip : register(c20),\n"
2993 "uniform float FogPlaneViewDist : register(c19),\n"
2994 "uniform float FogHeightFade : register(c17),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEOFFSETMAPPING\n"
2998 "uniform float OffsetMapping_Scale : register(c24),\n"
2999 "#endif\n"
3000 "\n"
3001 "#ifdef USEDEFERREDLIGHTMAP\n"
3002 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3003 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3004 "uniform half3 DeferredMod_Specular : register(c13),\n"
3005 "#endif\n"
3006 "uniform half3 Color_Ambient : register(c3),\n"
3007 "uniform half3 Color_Diffuse : register(c4),\n"
3008 "uniform half3 Color_Specular : register(c5),\n"
3009 "uniform half SpecularPower : register(c36),\n"
3010 "#ifdef USEGLOW\n"
3011 "uniform half3 Color_Glow : register(c6),\n"
3012 "#endif\n"
3013 "uniform half Alpha : register(c0),\n"
3014 "#ifdef USEREFLECTION\n"
3015 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3016 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3017 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3018 "uniform half4 ReflectColor : register(c26),\n"
3019 "#endif\n"
3020 "#ifdef USEREFLECTCUBE\n"
3021 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3022 "uniform sampler Texture_ReflectMask : register(s5),\n"
3023 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3024 "#endif\n"
3025 "#ifdef MODE_LIGHTDIRECTION\n"
3026 "uniform half3 LightColor : register(c21),\n"
3027 "#endif\n"
3028 "#ifdef MODE_LIGHTSOURCE\n"
3029 "uniform half3 LightColor : register(c21),\n"
3030 "#endif\n"
3031 "\n"
3032 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3033 "uniform sampler Texture_Attenuation : register(s9),\n"
3034 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3035 "#endif\n"
3036 "\n"
3037 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3038 "\n"
3039 "#ifdef USESHADOWMAP2D\n"
3040 "# ifdef USESHADOWSAMPLER\n"
3041 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3042 "# else\n"
3043 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3044 "# endif\n"
3045 "#endif\n"
3046 "\n"
3047 "#ifdef USESHADOWMAPVSDCT\n"
3048 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3049 "#endif\n"
3050 "\n"
3051 "#if defined(USESHADOWMAP2D)\n"
3052 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3053 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3054 "#endif\n"
3055 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3056 "\n"
3057 "out float4 gl_FragColor : COLOR\n"
3058 ")\n"
3059 "{\n"
3060 "       float2 TexCoord = TexCoordBoth.xy;\n"
3061 "#ifdef USEVERTEXTEXTUREBLEND\n"
3062 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3063 "#endif\n"
3064 "#ifdef USEOFFSETMAPPING\n"
3065 "       // apply offsetmapping\n"
3066 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3067 "#define TexCoord TexCoordOffset\n"
3068 "#endif\n"
3069 "\n"
3070 "       // combine the diffuse textures (base, pants, shirt)\n"
3071 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3072 "#ifdef USEALPHAKILL\n"
3073 "       if (color.a < 0.5)\n"
3074 "               discard;\n"
3075 "#endif\n"
3076 "       color.a *= Alpha;\n"
3077 "#ifdef USECOLORMAPPING\n"
3078 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3079 "#endif\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3082 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3083 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3084 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3085 "       color.a = 1.0;\n"
3086 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3087 "#endif\n"
3088 "\n"
3089 "       // get the surface normal\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3092 "#else\n"
3093 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3094 "#endif\n"
3095 "\n"
3096 "       // get the material colors\n"
3097 "       half3 diffusetex = color.rgb;\n"
3098 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3099 "# ifdef USEVERTEXTEXTUREBLEND\n"
3100 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3101 "# else\n"
3102 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3103 "# endif\n"
3104 "#endif\n"
3105 "\n"
3106 "#ifdef USEREFLECTCUBE\n"
3107 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3108 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3109 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3110 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3111 "#endif\n"
3112 "\n"
3113 "\n"
3114 "\n"
3115 "\n"
3116 "#ifdef MODE_LIGHTSOURCE\n"
3117 "       // light source\n"
3118 "#ifdef USEDIFFUSE\n"
3119 "       half3 lightnormal = half3(normalize(LightVector));\n"
3120 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3121 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3122 "#ifdef USESPECULAR\n"
3123 "#ifdef USEEXACTSPECULARMATH\n"
3124 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3125 "#else\n"
3126 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3127 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3128 "#endif\n"
3129 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3130 "#endif\n"
3131 "#else\n"
3132 "       color.rgb = diffusetex * Color_Ambient;\n"
3133 "#endif\n"
3134 "       color.rgb *= LightColor;\n"
3135 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3136 "#if defined(USESHADOWMAP2D)\n"
3137 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3138 "#ifdef USESHADOWMAPVSDCT\n"
3139 ", Texture_CubeProjection\n"
3140 "#endif\n"
3141 "       ));\n"
3142 "\n"
3143 "#endif\n"
3144 "# ifdef USECUBEFILTER\n"
3145 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3146 "# endif\n"
3147 "\n"
3148 "#ifdef USESHADOWMAP2D\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3151 "#else\n"
3152 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3153 "#endif\n"
3154 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3155 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3156 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3157 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3158 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3159 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3160 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3161 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3162 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3163 "//     color.r = half(shadowmaptc.z);\n"
3164 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3165 "//     color.r = half(shadowmaptc.z);\n"
3166 "//     color.r = 1;\n"
3167 "//     color.rgb = abs(CubeVector);\n"
3168 "#endif\n"
3169 "//     color.rgb = half3(1,1,1);\n"
3170 "#endif // MODE_LIGHTSOURCE\n"
3171 "\n"
3172 "\n"
3173 "\n"
3174 "\n"
3175 "#ifdef MODE_LIGHTDIRECTION\n"
3176 "#define SHADING\n"
3177 "#ifdef USEDIFFUSE\n"
3178 "       half3 lightnormal = half3(normalize(LightVector));\n"
3179 "#endif\n"
3180 "#define lightcolor LightColor\n"
3181 "#endif // MODE_LIGHTDIRECTION\n"
3182 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3183 "#define SHADING\n"
3184 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3185 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3186 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3187 "       // convert modelspace light vector to tangentspace\n"
3188 "       half3 lightnormal;\n"
3189 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3190 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3191 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3192 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3193 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3194 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3195 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3196 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3197 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3198 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3199 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3200 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3201 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3202 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3203 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3204 "#define SHADING\n"
3205 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3206 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3207 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3208 "#endif\n"
3209 "\n"
3210 "\n"
3211 "\n"
3212 "\n"
3213 "#ifdef MODE_FAKELIGHT\n"
3214 "#define SHADING\n"
3215 "half3 lightnormal = half3(normalize(EyeVector));\n"
3216 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3217 "#endif // MODE_FAKELIGHT\n"
3218 "\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "#ifdef MODE_LIGHTMAP\n"
3223 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_LIGHTMAP\n"
3225 "#ifdef MODE_VERTEXCOLOR\n"
3226 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3227 "#endif // MODE_VERTEXCOLOR\n"
3228 "#ifdef MODE_FLATCOLOR\n"
3229 "       color.rgb = diffusetex * Color_Ambient;\n"
3230 "#endif // MODE_FLATCOLOR\n"
3231 "\n"
3232 "\n"
3233 "\n"
3234 "\n"
3235 "#ifdef SHADING\n"
3236 "# ifdef USEDIFFUSE\n"
3237 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3238 "#  ifdef USESPECULAR\n"
3239 "#   ifdef USEEXACTSPECULARMATH\n"
3240 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3241 "#   else\n"
3242 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3243 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3244 "#   endif\n"
3245 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3246 "#  else\n"
3247 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3248 "#  endif\n"
3249 "# else\n"
3250 "       color.rgb = diffusetex * Color_Ambient;\n"
3251 "# endif\n"
3252 "#endif\n"
3253 "\n"
3254 "#ifdef USESHADOWMAPORTHO\n"
3255 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3256 "#endif\n"
3257 "\n"
3258 "#ifdef USEDEFERREDLIGHTMAP\n"
3259 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3260 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3261 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3262 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3263 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3264 "#endif\n"
3265 "\n"
3266 "#ifdef USEGLOW\n"
3267 "#ifdef USEVERTEXTEXTUREBLEND\n"
3268 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3269 "#else\n"
3270 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3271 "#endif\n"
3272 "#endif\n"
3273 "\n"
3274 "#ifdef USEFOG\n"
3275 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3276 "#endif\n"
3277 "\n"
3278 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3279 "#ifdef USEREFLECTION\n"
3280 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3281 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3282 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3283 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3284 "       // FIXME temporary hack to detect the case that the reflection\n"
3285 "       // gets blackened at edges due to leaving the area that contains actual\n"
3286 "       // content.\n"
3287 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3288 "       // 'appening.\n"
3289 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3290 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3291 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3292 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3293 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3294 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3295 "#endif\n"
3296 "\n"
3297 "       gl_FragColor = float4(color);\n"
3298 "}\n"
3299 "#endif // FRAGMENT_SHADER\n"
3300 "\n"
3301 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3302 "#endif // !MODE_DEFERREDGEOMETRY\n"
3303 "#endif // !MODE_WATER\n"
3304 "#endif // !MODE_REFRACTION\n"
3305 "#endif // !MODE_BLOOMBLUR\n"
3306 "#endif // !MODE_GENERIC\n"
3307 "#endif // !MODE_POSTPROCESS\n"
3308 "#endif // !MODE_SHOWDEPTH\n"
3309 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3310 ;
3311
3312 char *glslshaderstring = NULL;
3313 char *cgshaderstring = NULL;
3314 char *hlslshaderstring = NULL;
3315
3316 //=======================================================================================================================================================
3317
3318 typedef struct shaderpermutationinfo_s
3319 {
3320         const char *pretext;
3321         const char *name;
3322 }
3323 shaderpermutationinfo_t;
3324
3325 typedef struct shadermodeinfo_s
3326 {
3327         const char *vertexfilename;
3328         const char *geometryfilename;
3329         const char *fragmentfilename;
3330         const char *pretext;
3331         const char *name;
3332 }
3333 shadermodeinfo_t;
3334
3335 typedef enum shaderpermutation_e
3336 {
3337         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3338         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3339         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3340         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3341         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3342         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3343         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3344         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3345         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3346         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3347         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3348         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3349         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3350         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3351         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3352         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3353         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3354         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3355         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3356         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3357         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3358         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3359         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3360         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3361         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3362         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3363         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3364         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3365         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3366 }
3367 shaderpermutation_t;
3368
3369 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3370 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3371 {
3372         {"#define USEDIFFUSE\n", " diffuse"},
3373         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3374         {"#define USEVIEWTINT\n", " viewtint"},
3375         {"#define USECOLORMAPPING\n", " colormapping"},
3376         {"#define USESATURATION\n", " saturation"},
3377         {"#define USEFOGINSIDE\n", " foginside"},
3378         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3379         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3380         {"#define USEGAMMARAMPS\n", " gammaramps"},
3381         {"#define USECUBEFILTER\n", " cubefilter"},
3382         {"#define USEGLOW\n", " glow"},
3383         {"#define USEBLOOM\n", " bloom"},
3384         {"#define USESPECULAR\n", " specular"},
3385         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3386         {"#define USEREFLECTION\n", " reflection"},
3387         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3388         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3389         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3390         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3391         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3392         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3393         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3394         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3395         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3396         {"#define USEALPHAKILL\n", " alphakill"},
3397         {"#define USEREFLECTCUBE\n", " reflectcube"},
3398         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3399 };
3400
3401 // this enum selects which of the glslshadermodeinfo entries should be used
3402 typedef enum shadermode_e
3403 {
3404         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3405         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3406         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3407         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3408         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3409         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3410         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3411         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3412         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3413         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3414         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3415         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3416         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3417         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3418         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3419         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3420         SHADERMODE_COUNT
3421 }
3422 shadermode_t;
3423
3424 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3425 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3426 {
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3429         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3443 };
3444
3445 #ifdef SUPPORTCG
3446 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3447 {
3448         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3449         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3464 };
3465 #endif
3466
3467 #ifdef SUPPORTD3D
3468 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3469 {
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3475         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3476         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3486 };
3487 #endif
3488
3489 struct r_glsl_permutation_s;
3490 typedef struct r_glsl_permutation_s
3491 {
3492         /// hash lookup data
3493         struct r_glsl_permutation_s *hashnext;
3494         unsigned int mode;
3495         unsigned int permutation;
3496
3497         /// indicates if we have tried compiling this permutation already
3498         qboolean compiled;
3499         /// 0 if compilation failed
3500         int program;
3501         /// locations of detected uniforms in program object, or -1 if not found
3502         int loc_Texture_First;
3503         int loc_Texture_Second;
3504         int loc_Texture_GammaRamps;
3505         int loc_Texture_Normal;
3506         int loc_Texture_Color;
3507         int loc_Texture_Gloss;
3508         int loc_Texture_Glow;
3509         int loc_Texture_SecondaryNormal;
3510         int loc_Texture_SecondaryColor;
3511         int loc_Texture_SecondaryGloss;
3512         int loc_Texture_SecondaryGlow;
3513         int loc_Texture_Pants;
3514         int loc_Texture_Shirt;
3515         int loc_Texture_FogHeightTexture;
3516         int loc_Texture_FogMask;
3517         int loc_Texture_Lightmap;
3518         int loc_Texture_Deluxemap;
3519         int loc_Texture_Attenuation;
3520         int loc_Texture_Cube;
3521         int loc_Texture_Refraction;
3522         int loc_Texture_Reflection;
3523         int loc_Texture_ShadowMap2D;
3524         int loc_Texture_CubeProjection;
3525         int loc_Texture_ScreenDepth;
3526         int loc_Texture_ScreenNormalMap;
3527         int loc_Texture_ScreenDiffuse;
3528         int loc_Texture_ScreenSpecular;
3529         int loc_Texture_ReflectMask;
3530         int loc_Texture_ReflectCube;
3531         int loc_Alpha;
3532         int loc_BloomBlur_Parameters;
3533         int loc_ClientTime;
3534         int loc_Color_Ambient;
3535         int loc_Color_Diffuse;
3536         int loc_Color_Specular;
3537         int loc_Color_Glow;
3538         int loc_Color_Pants;
3539         int loc_Color_Shirt;
3540         int loc_DeferredColor_Ambient;
3541         int loc_DeferredColor_Diffuse;
3542         int loc_DeferredColor_Specular;
3543         int loc_DeferredMod_Diffuse;
3544         int loc_DeferredMod_Specular;
3545         int loc_DistortScaleRefractReflect;
3546         int loc_EyePosition;
3547         int loc_FogColor;
3548         int loc_FogHeightFade;
3549         int loc_FogPlane;
3550         int loc_FogPlaneViewDist;
3551         int loc_FogRangeRecip;
3552         int loc_LightColor;
3553         int loc_LightDir;
3554         int loc_LightPosition;
3555         int loc_OffsetMapping_Scale;
3556         int loc_PixelSize;
3557         int loc_ReflectColor;
3558         int loc_ReflectFactor;
3559         int loc_ReflectOffset;
3560         int loc_RefractColor;
3561         int loc_Saturation;
3562         int loc_ScreenCenterRefractReflect;
3563         int loc_ScreenScaleRefractReflect;
3564         int loc_ScreenToDepth;
3565         int loc_ShadowMap_Parameters;
3566         int loc_ShadowMap_TextureScale;
3567         int loc_SpecularPower;
3568         int loc_UserVec1;
3569         int loc_UserVec2;
3570         int loc_UserVec3;
3571         int loc_UserVec4;
3572         int loc_ViewTintColor;
3573         int loc_ViewToLight;
3574         int loc_ModelToLight;
3575         int loc_TexMatrix;
3576         int loc_BackgroundTexMatrix;
3577         int loc_ModelViewProjectionMatrix;
3578         int loc_ModelViewMatrix;
3579         int loc_PixelToScreenTexCoord;
3580         int loc_ModelToReflectCube;
3581         int loc_ShadowMapMatrix;
3582         int loc_BloomColorSubtract;
3583         int loc_NormalmapScrollBlend;
3584 }
3585 r_glsl_permutation_t;
3586
3587 #define SHADERPERMUTATION_HASHSIZE 256
3588
3589
3590 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3591 // these can NOT degrade! only use for simple stuff
3592 enum
3593 {
3594         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3595         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3596         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3599         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3600 };
3601 #define SHADERSTATICPARMS_COUNT 6
3602
3603 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3604 static int shaderstaticparms_count = 0;
3605
3606 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3607 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3608 qboolean R_CompileShader_CheckStaticParms(void)
3609 {
3610         static int r_compileshader_staticparms_save[1];
3611         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3612         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3613
3614         // detect all
3615         if (r_glsl_saturation_redcompensate.integer)
3616                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3617         if (r_shadow_glossexact.integer)
3618                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3619         if (r_glsl_postprocess.integer)
3620         {
3621                 if (r_glsl_postprocess_uservec1_enable.integer)
3622                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3623                 if (r_glsl_postprocess_uservec2_enable.integer)
3624                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3625                 if (r_glsl_postprocess_uservec3_enable.integer)
3626                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3627                 if (r_glsl_postprocess_uservec4_enable.integer)
3628                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3629         }
3630         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3631 }
3632
3633 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3634         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3635                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3636         else \
3637                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3638 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3639 {
3640         shaderstaticparms_count = 0;
3641
3642         // emit all
3643         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3648         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3649 }
3650
3651 /// information about each possible shader permutation
3652 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3653 /// currently selected permutation
3654 r_glsl_permutation_t *r_glsl_permutation;
3655 /// storage for permutations linked in the hash table
3656 memexpandablearray_t r_glsl_permutationarray;
3657
3658 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3659 {
3660         //unsigned int hashdepth = 0;
3661         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3662         r_glsl_permutation_t *p;
3663         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3664         {
3665                 if (p->mode == mode && p->permutation == permutation)
3666                 {
3667                         //if (hashdepth > 10)
3668                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3669                         return p;
3670                 }
3671                 //hashdepth++;
3672         }
3673         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3674         p->mode = mode;
3675         p->permutation = permutation;
3676         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3677         r_glsl_permutationhash[mode][hashindex] = p;
3678         //if (hashdepth > 10)
3679         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3680         return p;
3681 }
3682
3683 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3684 {
3685         char *shaderstring;
3686         if (!filename || !filename[0])
3687                 return NULL;
3688         if (!strcmp(filename, "glsl/default.glsl"))
3689         {
3690                 if (!glslshaderstring)
3691                 {
3692                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3693                         if (glslshaderstring)
3694                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3695                         else
3696                                 glslshaderstring = (char *)builtinshaderstring;
3697                 }
3698                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3699                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3700                 return shaderstring;
3701         }
3702         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703         if (shaderstring)
3704         {
3705                 if (printfromdisknotice)
3706                         Con_DPrintf("from disk %s... ", filename);
3707                 return shaderstring;
3708         }
3709         return shaderstring;
3710 }
3711
3712 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3713 {
3714         int i;
3715         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3716         char *vertexstring, *geometrystring, *fragmentstring;
3717         char permutationname[256];
3718         int vertstrings_count = 0;
3719         int geomstrings_count = 0;
3720         int fragstrings_count = 0;
3721         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3722         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3723         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724
3725         if (p->compiled)
3726                 return;
3727         p->compiled = true;
3728         p->program = 0;
3729
3730         permutationname[0] = 0;
3731         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3732         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3733         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3734
3735         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3736
3737         // the first pretext is which type of shader to compile as
3738         // (later these will all be bound together as a program object)
3739         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3740         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3741         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3742
3743         // the second pretext is the mode (for example a light source)
3744         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3745         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3746         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3747         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3748
3749         // now add all the permutation pretexts
3750         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3751         {
3752                 if (permutation & (1<<i))
3753                 {
3754                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3755                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3756                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3757                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3758                 }
3759                 else
3760                 {
3761                         // keep line numbers correct
3762                         vertstrings_list[vertstrings_count++] = "\n";
3763                         geomstrings_list[geomstrings_count++] = "\n";
3764                         fragstrings_list[fragstrings_count++] = "\n";
3765                 }
3766         }
3767
3768         // add static parms
3769         R_CompileShader_AddStaticParms(mode, permutation);
3770         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3771         vertstrings_count += shaderstaticparms_count;
3772         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773         geomstrings_count += shaderstaticparms_count;
3774         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775         fragstrings_count += shaderstaticparms_count;
3776
3777         // now append the shader text itself
3778         vertstrings_list[vertstrings_count++] = vertexstring;
3779         geomstrings_list[geomstrings_count++] = geometrystring;
3780         fragstrings_list[fragstrings_count++] = fragmentstring;
3781
3782         // if any sources were NULL, clear the respective list
3783         if (!vertexstring)
3784                 vertstrings_count = 0;
3785         if (!geometrystring)
3786                 geomstrings_count = 0;
3787         if (!fragmentstring)
3788                 fragstrings_count = 0;
3789
3790         // compile the shader program
3791         if (vertstrings_count + geomstrings_count + fragstrings_count)
3792                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3793         if (p->program)
3794         {
3795                 CHECKGLERROR
3796                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3797                 // look up all the uniform variable names we care about, so we don't
3798                 // have to look them up every time we set them
3799
3800                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3801                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3802                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3803                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3804                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3805                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3806                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3807                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3808                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3809                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3810                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3811                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3812                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3813                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3814                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3815                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3816                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3817                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3818                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3819                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3820                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3821                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3822                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3823                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3824                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3825                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3826                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3827                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3828                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3829                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3830                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3831                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3832                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3833                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3834                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3835                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3836                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3837                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3838                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3839                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3840                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3841                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3842                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3843                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3844                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3845                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3846                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3847                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3848                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3849                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3850                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3851                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3852                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3853                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3854                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3855                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3856                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3857                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3858                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3859                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3860                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3861                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3862                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3863                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3864                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3865                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3866                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3867                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3868                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3869                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3870                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3871                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3872                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3873                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3874                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3875                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3876                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3877                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3878                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3879                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3880                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3881                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3882                 // initialize the samplers to refer to the texture units we use
3883                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3884                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3885                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3886                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3887                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3888                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3889                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3890                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3891                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3892                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3893                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3894                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3895                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3896                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3897                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3898                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3899                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3900                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3901                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3902                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3903                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3904                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3905                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3906                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3907                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3908                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3909                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3910                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3911                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3912                 CHECKGLERROR
3913                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3914         }
3915         else
3916                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3917
3918         // free the strings
3919         if (vertexstring)
3920                 Mem_Free(vertexstring);
3921         if (geometrystring)
3922                 Mem_Free(geometrystring);
3923         if (fragmentstring)
3924                 Mem_Free(fragmentstring);
3925 }
3926
3927 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3928 {
3929         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3930         if (r_glsl_permutation != perm)
3931         {
3932                 r_glsl_permutation = perm;
3933                 if (!r_glsl_permutation->program)
3934                 {
3935                         if (!r_glsl_permutation->compiled)
3936                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3937                         if (!r_glsl_permutation->program)
3938                         {
3939                                 // remove features until we find a valid permutation
3940                                 int i;
3941                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3942                                 {
3943                                         // reduce i more quickly whenever it would not remove any bits
3944                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3945                                         if (!(permutation & j))
3946                                                 continue;
3947                                         permutation -= j;
3948                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3949                                         if (!r_glsl_permutation->compiled)
3950                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3951                                         if (r_glsl_permutation->program)
3952                                                 break;
3953                                 }
3954                                 if (i >= SHADERPERMUTATION_COUNT)
3955                                 {
3956                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3957                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3958                                         qglUseProgramObjectARB(0);CHECKGLERROR
3959                                         return; // no bit left to clear, entire mode is broken
3960                                 }
3961                         }
3962                 }
3963                 CHECKGLERROR
3964                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3965         }
3966         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3967         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3968         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3969 }
3970
3971 #ifdef SUPPORTCG
3972 #include <Cg/cgGL.h>
3973 struct r_cg_permutation_s;
3974 typedef struct r_cg_permutation_s
3975 {
3976         /// hash lookup data
3977         struct r_cg_permutation_s *hashnext;
3978         unsigned int mode;
3979         unsigned int permutation;
3980
3981         /// indicates if we have tried compiling this permutation already
3982         qboolean compiled;
3983         /// 0 if compilation failed
3984         CGprogram vprogram;
3985         CGprogram fprogram;
3986         /// locations of detected parameters in programs, or NULL if not found
3987         CGparameter vp_EyePosition;
3988         CGparameter vp_FogPlane;
3989         CGparameter vp_LightDir;
3990         CGparameter vp_LightPosition;
3991         CGparameter vp_ModelToLight;
3992         CGparameter vp_TexMatrix;
3993         CGparameter vp_BackgroundTexMatrix;
3994         CGparameter vp_ModelViewProjectionMatrix;
3995         CGparameter vp_ModelViewMatrix;
3996         CGparameter vp_ShadowMapMatrix;
3997
3998         CGparameter fp_Texture_First;
3999         CGparameter fp_Texture_Second;
4000         CGparameter fp_Texture_GammaRamps;
4001         CGparameter fp_Texture_Normal;
4002         CGparameter fp_Texture_Color;
4003         CGparameter fp_Texture_Gloss;
4004         CGparameter fp_Texture_Glow;
4005         CGparameter fp_Texture_SecondaryNormal;
4006         CGparameter fp_Texture_SecondaryColor;
4007         CGparameter fp_Texture_SecondaryGloss;
4008         CGparameter fp_Texture_SecondaryGlow;
4009         CGparameter fp_Texture_Pants;
4010         CGparameter fp_Texture_Shirt;
4011         CGparameter fp_Texture_FogHeightTexture;
4012         CGparameter fp_Texture_FogMask;
4013         CGparameter fp_Texture_Lightmap;
4014         CGparameter fp_Texture_Deluxemap;
4015         CGparameter fp_Texture_Attenuation;
4016         CGparameter fp_Texture_Cube;
4017         CGparameter fp_Texture_Refraction;
4018         CGparameter fp_Texture_Reflection;
4019         CGparameter fp_Texture_ShadowMap2D;
4020         CGparameter fp_Texture_CubeProjection;
4021         CGparameter fp_Texture_ScreenDepth;
4022         CGparameter fp_Texture_ScreenNormalMap;
4023         CGparameter fp_Texture_ScreenDiffuse;
4024         CGparameter fp_Texture_ScreenSpecular;
4025         CGparameter fp_Texture_ReflectMask;
4026         CGparameter fp_Texture_ReflectCube;
4027         CGparameter fp_Alpha;
4028         CGparameter fp_BloomBlur_Parameters;
4029         CGparameter fp_ClientTime;
4030         CGparameter fp_Color_Ambient;
4031         CGparameter fp_Color_Diffuse;
4032         CGparameter fp_Color_Specular;
4033         CGparameter fp_Color_Glow;
4034         CGparameter fp_Color_Pants;
4035         CGparameter fp_Color_Shirt;
4036         CGparameter fp_DeferredColor_Ambient;
4037         CGparameter fp_DeferredColor_Diffuse;
4038         CGparameter fp_DeferredColor_Specular;
4039         CGparameter fp_DeferredMod_Diffuse;
4040         CGparameter fp_DeferredMod_Specular;
4041         CGparameter fp_DistortScaleRefractReflect;
4042         CGparameter fp_EyePosition;
4043         CGparameter fp_FogColor;
4044         CGparameter fp_FogHeightFade;
4045         CGparameter fp_FogPlane;
4046         CGparameter fp_FogPlaneViewDist;
4047         CGparameter fp_FogRangeRecip;
4048         CGparameter fp_LightColor;
4049         CGparameter fp_LightDir;
4050         CGparameter fp_LightPosition;
4051         CGparameter fp_OffsetMapping_Scale;
4052         CGparameter fp_PixelSize;
4053         CGparameter fp_ReflectColor;
4054         CGparameter fp_ReflectFactor;
4055         CGparameter fp_ReflectOffset;
4056         CGparameter fp_RefractColor;
4057         CGparameter fp_Saturation;
4058         CGparameter fp_ScreenCenterRefractReflect;
4059         CGparameter fp_ScreenScaleRefractReflect;
4060         CGparameter fp_ScreenToDepth;
4061         CGparameter fp_ShadowMap_Parameters;
4062         CGparameter fp_ShadowMap_TextureScale;
4063         CGparameter fp_SpecularPower;
4064         CGparameter fp_UserVec1;
4065         CGparameter fp_UserVec2;
4066         CGparameter fp_UserVec3;
4067         CGparameter fp_UserVec4;
4068         CGparameter fp_ViewTintColor;
4069         CGparameter fp_ViewToLight;
4070         CGparameter fp_PixelToScreenTexCoord;
4071         CGparameter fp_ModelToReflectCube;
4072         CGparameter fp_BloomColorSubtract;
4073         CGparameter fp_NormalmapScrollBlend;
4074 }
4075 r_cg_permutation_t;
4076
4077 /// information about each possible shader permutation
4078 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4079 /// currently selected permutation
4080 r_cg_permutation_t *r_cg_permutation;
4081 /// storage for permutations linked in the hash table
4082 memexpandablearray_t r_cg_permutationarray;
4083
4084 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4085
4086 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4087 {
4088         //unsigned int hashdepth = 0;
4089         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4090         r_cg_permutation_t *p;
4091         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4092         {
4093                 if (p->mode == mode && p->permutation == permutation)
4094                 {
4095                         //if (hashdepth > 10)
4096                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4097                         return p;
4098                 }
4099                 //hashdepth++;
4100         }
4101         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4102         p->mode = mode;
4103         p->permutation = permutation;
4104         p->hashnext = r_cg_permutationhash[mode][hashindex];
4105         r_cg_permutationhash[mode][hashindex] = p;
4106         //if (hashdepth > 10)
4107         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4108         return p;
4109 }
4110
4111 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4112 {
4113         char *shaderstring;
4114         if (!filename || !filename[0])
4115                 return NULL;
4116         if (!strcmp(filename, "cg/default.cg"))
4117         {
4118                 if (!cgshaderstring)
4119                 {
4120                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4121                         if (cgshaderstring)
4122                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4123                         else
4124                                 cgshaderstring = (char *)builtincgshaderstring;
4125                 }
4126                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4127                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4128                 return shaderstring;
4129         }
4130         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4131         if (shaderstring)
4132         {
4133                 if (printfromdisknotice)
4134                         Con_DPrintf("from disk %s... ", filename);
4135                 return shaderstring;
4136         }
4137         return shaderstring;
4138 }
4139
4140 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4141 {
4142         // TODO: load or create .fp and .vp shader files
4143 }
4144
4145 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4146 {
4147         int i;
4148         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4149         int vertstring_length = 0;
4150         int geomstring_length = 0;
4151         int fragstring_length = 0;
4152         char *t;
4153         char *vertexstring, *geometrystring, *fragmentstring;
4154         char *vertstring, *geomstring, *fragstring;
4155         char permutationname[256];
4156         char cachename[256];
4157         CGprofile vertexProfile;
4158         CGprofile fragmentProfile;
4159         int vertstrings_count = 0;
4160         int geomstrings_count = 0;
4161         int fragstrings_count = 0;
4162         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4163         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4164         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4165
4166         if (p->compiled)
4167                 return;
4168         p->compiled = true;
4169         p->vprogram = NULL;
4170         p->fprogram = NULL;
4171
4172         permutationname[0] = 0;
4173         cachename[0] = 0;
4174         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4175         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4176         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4177
4178         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4179         strlcat(cachename, "cg/", sizeof(cachename));
4180
4181         // the first pretext is which type of shader to compile as
4182         // (later these will all be bound together as a program object)
4183         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4184         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4185         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4186
4187         // the second pretext is the mode (for example a light source)
4188         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4189         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4190         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4191         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4192         strlcat(cachename, modeinfo->name, sizeof(cachename));
4193
4194         // now add all the permutation pretexts
4195         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4196         {
4197                 if (permutation & (1<<i))
4198                 {
4199                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4200                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4201                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4202                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4203                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4204                 }
4205                 else
4206                 {
4207                         // keep line numbers correct
4208                         vertstrings_list[vertstrings_count++] = "\n";
4209                         geomstrings_list[geomstrings_count++] = "\n";
4210                         fragstrings_list[fragstrings_count++] = "\n";
4211                 }
4212         }
4213
4214         // add static parms
4215         R_CompileShader_AddStaticParms(mode, permutation);
4216         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4217         vertstrings_count += shaderstaticparms_count;
4218         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4219         geomstrings_count += shaderstaticparms_count;
4220         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4221         fragstrings_count += shaderstaticparms_count;
4222
4223         // replace spaces in the cachename with _ characters
4224         for (i = 0;cachename[i];i++)
4225                 if (cachename[i] == ' ')
4226                         cachename[i] = '_';
4227
4228         // now append the shader text itself
4229         vertstrings_list[vertstrings_count++] = vertexstring;
4230         geomstrings_list[geomstrings_count++] = geometrystring;
4231         fragstrings_list[fragstrings_count++] = fragmentstring;
4232
4233         // if any sources were NULL, clear the respective list
4234         if (!vertexstring)
4235                 vertstrings_count = 0;
4236         if (!geometrystring)
4237                 geomstrings_count = 0;
4238         if (!fragmentstring)
4239                 fragstrings_count = 0;
4240
4241         vertstring_length = 0;
4242         for (i = 0;i < vertstrings_count;i++)
4243                 vertstring_length += strlen(vertstrings_list[i]);
4244         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4245         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4246                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4247
4248         geomstring_length = 0;
4249         for (i = 0;i < geomstrings_count;i++)
4250                 geomstring_length += strlen(geomstrings_list[i]);
4251         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4252         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4253                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4254
4255         fragstring_length = 0;
4256         for (i = 0;i < fragstrings_count;i++)
4257                 fragstring_length += strlen(fragstrings_list[i]);
4258         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4259         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4260                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4261
4262         CHECKGLERROR
4263         CHECKCGERROR
4264         //vertexProfile = CG_PROFILE_ARBVP1;
4265         //fragmentProfile = CG_PROFILE_ARBFP1;
4266         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4267         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4268         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4269         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4270         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4271         CHECKGLERROR
4272
4273         // try to load the cached shader, or generate one
4274         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4275
4276         // if caching failed, do a dynamic compile for now
4277         CHECKCGERROR
4278         if (vertstring[0] && !p->vprogram)
4279                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4280         CHECKCGERROR
4281         if (fragstring[0] && !p->fprogram)
4282                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4283         CHECKCGERROR
4284
4285         // look up all the uniform variable names we care about, so we don't
4286         // have to look them up every time we set them
4287         if (p->vprogram)
4288         {
4289                 CHECKCGERROR
4290                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4291                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4292                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4293                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4294                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4295                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4296                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4297                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4298                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4299                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4300                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4301                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4302                 CHECKCGERROR
4303         }
4304         if (p->fprogram)
4305         {
4306                 CHECKCGERROR
4307                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4308                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4309                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4310                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4311                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4312                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4313                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4314                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4315                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4316                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4317                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4318                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4319                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4320                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4321                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4322                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4323                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4324                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4325                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4326                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4327                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4328                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4329                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4330                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4331                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4332                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4333                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4334                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4335                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4336                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4337                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4338                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4339                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4340                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4341                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4342                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4343                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4344                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4345                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4346                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4347                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4348                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4349                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4350                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4351                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4352                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4353                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4354                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4355                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4356                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4357                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4358                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4359                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4360                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4361                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4362                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4363                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4364                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4365                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4366                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4367                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4368                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4369                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4370                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4371                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4372                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4373                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4374                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4375                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4376                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4377                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4378                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4379                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4380                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4381                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4382                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4383                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4384                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4385                 CHECKCGERROR
4386         }
4387
4388         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4389                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4390         else
4391                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4392
4393         // free the strings
4394         if (vertstring)
4395                 Mem_Free(vertstring);
4396         if (geomstring)
4397                 Mem_Free(geomstring);
4398         if (fragstring)
4399                 Mem_Free(fragstring);
4400         if (vertexstring)
4401                 Mem_Free(vertexstring);
4402         if (geometrystring)
4403                 Mem_Free(geometrystring);
4404         if (fragmentstring)
4405                 Mem_Free(fragmentstring);
4406 }
4407
4408 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4409 {
4410         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4411         CHECKGLERROR
4412         CHECKCGERROR
4413         if (r_cg_permutation != perm)
4414         {
4415                 r_cg_permutation = perm;
4416                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4417                 {
4418                         if (!r_cg_permutation->compiled)
4419                                 R_CG_CompilePermutation(perm, mode, permutation);
4420                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4421                         {
4422                                 // remove features until we find a valid permutation
4423                                 int i;
4424                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4425                                 {
4426                                         // reduce i more quickly whenever it would not remove any bits
4427                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4428                                         if (!(permutation & j))
4429                                                 continue;
4430                                         permutation -= j;
4431                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4432                                         if (!r_cg_permutation->compiled)
4433                                                 R_CG_CompilePermutation(perm, mode, permutation);
4434                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4435                                                 break;
4436                                 }
4437                                 if (i >= SHADERPERMUTATION_COUNT)
4438                                 {
4439                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4440                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4441                                         return; // no bit left to clear, entire mode is broken
4442                                 }
4443                         }
4444                 }
4445                 CHECKGLERROR
4446                 CHECKCGERROR
4447                 if (r_cg_permutation->vprogram)
4448                 {
4449                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4450                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4451                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4452                 }
4453                 else
4454                 {
4455                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4456                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4457                 }
4458                 if (r_cg_permutation->fprogram)
4459                 {
4460                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4461                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4462                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4463                 }
4464                 else
4465                 {
4466                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4467                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4468                 }
4469         }
4470         CHECKCGERROR
4471         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4472         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4473         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4474 }
4475
4476 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4477 {
4478         cgGLSetTextureParameter(param, R_GetTexture(tex));
4479         cgGLEnableTextureParameter(param);
4480 }
4481 #endif
4482
4483 #ifdef SUPPORTD3D
4484
4485 #ifdef SUPPORTD3D
4486 #include <d3d9.h>
4487 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4488 extern D3DCAPS9 vid_d3d9caps;
4489 #endif
4490
4491 struct r_hlsl_permutation_s;
4492 typedef struct r_hlsl_permutation_s
4493 {
4494         /// hash lookup data
4495         struct r_hlsl_permutation_s *hashnext;
4496         unsigned int mode;
4497         unsigned int permutation;
4498
4499         /// indicates if we have tried compiling this permutation already
4500         qboolean compiled;
4501         /// NULL if compilation failed
4502         IDirect3DVertexShader9 *vertexshader;
4503         IDirect3DPixelShader9 *pixelshader;
4504 }
4505 r_hlsl_permutation_t;
4506
4507 typedef enum D3DVSREGISTER_e
4508 {
4509         D3DVSREGISTER_TexMatrix = 0, // float4x4
4510         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4511         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4512         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4513         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4514         D3DVSREGISTER_ModelToLight = 20, // float4x4
4515         D3DVSREGISTER_EyePosition = 24,
4516         D3DVSREGISTER_FogPlane = 25,
4517         D3DVSREGISTER_LightDir = 26,
4518         D3DVSREGISTER_LightPosition = 27,
4519 }
4520 D3DVSREGISTER_t;
4521
4522 typedef enum D3DPSREGISTER_e
4523 {
4524         D3DPSREGISTER_Alpha = 0,
4525         D3DPSREGISTER_BloomBlur_Parameters = 1,
4526         D3DPSREGISTER_ClientTime = 2,
4527         D3DPSREGISTER_Color_Ambient = 3,
4528         D3DPSREGISTER_Color_Diffuse = 4,
4529         D3DPSREGISTER_Color_Specular = 5,
4530         D3DPSREGISTER_Color_Glow = 6,
4531         D3DPSREGISTER_Color_Pants = 7,
4532         D3DPSREGISTER_Color_Shirt = 8,
4533         D3DPSREGISTER_DeferredColor_Ambient = 9,
4534         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4535         D3DPSREGISTER_DeferredColor_Specular = 11,
4536         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4537         D3DPSREGISTER_DeferredMod_Specular = 13,
4538         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4539         D3DPSREGISTER_EyePosition = 15, // unused
4540         D3DPSREGISTER_FogColor = 16,
4541         D3DPSREGISTER_FogHeightFade = 17,
4542         D3DPSREGISTER_FogPlane = 18,
4543         D3DPSREGISTER_FogPlaneViewDist = 19,
4544         D3DPSREGISTER_FogRangeRecip = 20,
4545         D3DPSREGISTER_LightColor = 21,
4546         D3DPSREGISTER_LightDir = 22, // unused
4547         D3DPSREGISTER_LightPosition = 23,
4548         D3DPSREGISTER_OffsetMapping_Scale = 24,
4549         D3DPSREGISTER_PixelSize = 25,
4550         D3DPSREGISTER_ReflectColor = 26,
4551         D3DPSREGISTER_ReflectFactor = 27,
4552         D3DPSREGISTER_ReflectOffset = 28,
4553         D3DPSREGISTER_RefractColor = 29,
4554         D3DPSREGISTER_Saturation = 30,
4555         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4556         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4557         D3DPSREGISTER_ScreenToDepth = 33,
4558         D3DPSREGISTER_ShadowMap_Parameters = 34,
4559         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4560         D3DPSREGISTER_SpecularPower = 36,
4561         D3DPSREGISTER_UserVec1 = 37,
4562         D3DPSREGISTER_UserVec2 = 38,
4563         D3DPSREGISTER_UserVec3 = 39,
4564         D3DPSREGISTER_UserVec4 = 40,
4565         D3DPSREGISTER_ViewTintColor = 41,
4566         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4567         D3DPSREGISTER_BloomColorSubtract = 43,
4568         D3DPSREGISTER_ViewToLight = 44, // float4x4
4569         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4570         D3DPSREGISTER_NormalmapScrollBlend = 52,
4571         // next at 53
4572 }
4573 D3DPSREGISTER_t;
4574
4575 /// information about each possible shader permutation
4576 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4577 /// currently selected permutation
4578 r_hlsl_permutation_t *r_hlsl_permutation;
4579 /// storage for permutations linked in the hash table
4580 memexpandablearray_t r_hlsl_permutationarray;
4581
4582 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4583 {
4584         //unsigned int hashdepth = 0;
4585         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4586         r_hlsl_permutation_t *p;
4587         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4588         {
4589                 if (p->mode == mode && p->permutation == permutation)
4590                 {
4591                         //if (hashdepth > 10)
4592                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4593                         return p;
4594                 }
4595                 //hashdepth++;
4596         }
4597         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4598         p->mode = mode;
4599         p->permutation = permutation;
4600         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4601         r_hlsl_permutationhash[mode][hashindex] = p;
4602         //if (hashdepth > 10)
4603         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4604         return p;
4605 }
4606
4607 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4608 {
4609         char *shaderstring;
4610         if (!filename || !filename[0])
4611                 return NULL;
4612         if (!strcmp(filename, "hlsl/default.hlsl"))
4613         {
4614                 if (!hlslshaderstring)
4615                 {
4616                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4617                         if (hlslshaderstring)
4618                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4619                         else
4620                                 hlslshaderstring = (char *)builtincgshaderstring;
4621                 }
4622                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4623                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4624                 return shaderstring;
4625         }
4626         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4627         if (shaderstring)
4628         {
4629                 if (printfromdisknotice)
4630                         Con_DPrintf("from disk %s... ", filename);
4631                 return shaderstring;
4632         }
4633         return shaderstring;
4634 }
4635
4636 #include <d3dx9.h>
4637 //#include <d3dx9shader.h>
4638 //#include <d3dx9mesh.h>
4639
4640 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4641 {
4642         DWORD *vsbin = NULL;
4643         DWORD *psbin = NULL;
4644         fs_offset_t vsbinsize;
4645         fs_offset_t psbinsize;
4646 //      IDirect3DVertexShader9 *vs = NULL;
4647 //      IDirect3DPixelShader9 *ps = NULL;
4648         ID3DXBuffer *vslog = NULL;
4649         ID3DXBuffer *vsbuffer = NULL;
4650         ID3DXConstantTable *vsconstanttable = NULL;
4651         ID3DXBuffer *pslog = NULL;
4652         ID3DXBuffer *psbuffer = NULL;
4653         ID3DXConstantTable *psconstanttable = NULL;
4654         int vsresult = 0;
4655         int psresult = 0;
4656         char temp[MAX_INPUTLINE];
4657         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4658         qboolean debugshader = gl_paranoid.integer != 0;
4659         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4660         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4661         if (!debugshader)
4662         {
4663                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4664                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4665         }
4666         if ((!vsbin && vertstring) || (!psbin && fragstring))
4667         {
4668                 const char* dllnames_d3dx9 [] =
4669                 {
4670                         "d3dx9_43.dll",
4671                         "d3dx9_42.dll",
4672                         "d3dx9_41.dll",
4673                         "d3dx9_40.dll",
4674                         "d3dx9_39.dll",
4675                         "d3dx9_38.dll",
4676                         "d3dx9_37.dll",
4677                         "d3dx9_36.dll",
4678                         "d3dx9_35.dll",
4679                         "d3dx9_34.dll",
4680                         "d3dx9_33.dll",
4681                         "d3dx9_32.dll",
4682                         "d3dx9_31.dll",
4683                         "d3dx9_30.dll",
4684                         "d3dx9_29.dll",
4685                         "d3dx9_28.dll",
4686                         "d3dx9_27.dll",
4687                         "d3dx9_26.dll",
4688                         "d3dx9_25.dll",
4689                         "d3dx9_24.dll",
4690                         NULL
4691                 };
4692                 dllhandle_t d3dx9_dll = NULL;
4693                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4694                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4695                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4696                 dllfunction_t d3dx9_dllfuncs[] =
4697                 {
4698                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4699                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4700                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4701                         {NULL, NULL}
4702                 };
4703                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4704                 {
4705                         DWORD shaderflags = 0;
4706                         if (debugshader)
4707                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4708                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4709                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4710                         if (vertstring && vertstring[0])
4711                         {
4712                                 if (debugshader)
4713                                 {
4714 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4715 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4716                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4717                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4718                                 }
4719                                 else
4720                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4721                                 if (vsbuffer)
4722                                 {
4723                                         vsbinsize = vsbuffer->GetBufferSize();
4724                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4725                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4726                                         vsbuffer->Release();
4727                                 }
4728                                 if (vslog)
4729                                 {
4730                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4731                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4732                                         vslog->Release();
4733                                 }
4734                         }
4735                         if (fragstring && fragstring[0])
4736                         {
4737                                 if (debugshader)
4738                                 {
4739 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4740 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4741                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4742                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4743                                 }
4744                                 else
4745                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4746                                 if (psbuffer)
4747                                 {
4748                                         psbinsize = psbuffer->GetBufferSize();
4749                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4750                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4751                                         psbuffer->Release();
4752                                 }
4753                                 if (pslog)
4754                                 {
4755                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4756                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4757                                         pslog->Release();
4758                                 }
4759                         }
4760                         Sys_UnloadLibrary(&d3dx9_dll);
4761                 }
4762                 else
4763                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4764         }
4765         if (vsbin && psbin)
4766         {
4767                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4768                 if (FAILED(vsresult))
4769                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4770                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4771                 if (FAILED(psresult))
4772                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4773         }
4774         // free the shader data
4775         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4776         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4777 }
4778
4779 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4780 {
4781         int i;
4782         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4783         int vertstring_length = 0;
4784         int geomstring_length = 0;
4785         int fragstring_length = 0;
4786         char *t;
4787         char *vertexstring, *geometrystring, *fragmentstring;
4788         char *vertstring, *geomstring, *fragstring;
4789         char permutationname[256];
4790         char cachename[256];
4791         int vertstrings_count = 0;
4792         int geomstrings_count = 0;
4793         int fragstrings_count = 0;
4794         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4795         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4796         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4797
4798         if (p->compiled)
4799                 return;
4800         p->compiled = true;
4801         p->vertexshader = NULL;
4802         p->pixelshader = NULL;
4803
4804         permutationname[0] = 0;
4805         cachename[0] = 0;
4806         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4807         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4808         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4809
4810         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4811         strlcat(cachename, "hlsl/", sizeof(cachename));
4812
4813         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4814         vertstrings_count = 0;
4815         geomstrings_count = 0;
4816         fragstrings_count = 0;
4817         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4818         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4819         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4820
4821         // the first pretext is which type of shader to compile as
4822         // (later these will all be bound together as a program object)
4823         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4824         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4825         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4826
4827         // the second pretext is the mode (for example a light source)
4828         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4829         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4830         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4831         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4832         strlcat(cachename, modeinfo->name, sizeof(cachename));
4833
4834         // now add all the permutation pretexts
4835         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4836         {
4837                 if (permutation & (1<<i))
4838                 {
4839                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4840                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4841                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4842                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4843                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4844                 }
4845                 else
4846                 {
4847                         // keep line numbers correct
4848                         vertstrings_list[vertstrings_count++] = "\n";
4849                         geomstrings_list[geomstrings_count++] = "\n";
4850                         fragstrings_list[fragstrings_count++] = "\n";
4851                 }
4852         }
4853
4854         // add static parms
4855         R_CompileShader_AddStaticParms(mode, permutation);
4856         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4857         vertstrings_count += shaderstaticparms_count;
4858         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4859         geomstrings_count += shaderstaticparms_count;
4860         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4861         fragstrings_count += shaderstaticparms_count;
4862
4863         // replace spaces in the cachename with _ characters
4864         for (i = 0;cachename[i];i++)
4865                 if (cachename[i] == ' ')
4866                         cachename[i] = '_';
4867
4868         // now append the shader text itself
4869         vertstrings_list[vertstrings_count++] = vertexstring;
4870         geomstrings_list[geomstrings_count++] = geometrystring;
4871         fragstrings_list[fragstrings_count++] = fragmentstring;
4872
4873         // if any sources were NULL, clear the respective list
4874         if (!vertexstring)
4875                 vertstrings_count = 0;
4876         if (!geometrystring)
4877                 geomstrings_count = 0;
4878         if (!fragmentstring)
4879                 fragstrings_count = 0;
4880
4881         vertstring_length = 0;
4882         for (i = 0;i < vertstrings_count;i++)
4883                 vertstring_length += strlen(vertstrings_list[i]);
4884         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4885         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4886                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4887
4888         geomstring_length = 0;
4889         for (i = 0;i < geomstrings_count;i++)
4890                 geomstring_length += strlen(geomstrings_list[i]);
4891         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4892         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4893                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4894
4895         fragstring_length = 0;
4896         for (i = 0;i < fragstrings_count;i++)
4897                 fragstring_length += strlen(fragstrings_list[i]);
4898         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4899         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4900                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4901
4902         // try to load the cached shader, or generate one
4903         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4904
4905         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4906                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4907         else
4908                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4909
4910         // free the strings
4911         if (vertstring)
4912                 Mem_Free(vertstring);
4913         if (geomstring)
4914                 Mem_Free(geomstring);
4915         if (fragstring)
4916                 Mem_Free(fragstring);
4917         if (vertexstring)
4918                 Mem_Free(vertexstring);
4919         if (geometrystring)
4920                 Mem_Free(geometrystring);
4921         if (fragmentstring)
4922                 Mem_Free(fragmentstring);
4923 }
4924
4925 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4926 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4927 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4928 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4929 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4930 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4931
4932 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4933 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4934 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4935 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4936 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4937 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4938
4939 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4940 {
4941         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4942         if (r_hlsl_permutation != perm)
4943         {
4944                 r_hlsl_permutation = perm;
4945                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4946                 {
4947                         if (!r_hlsl_permutation->compiled)
4948                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4949                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4950                         {
4951                                 // remove features until we find a valid permutation
4952                                 int i;
4953                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4954                                 {
4955                                         // reduce i more quickly whenever it would not remove any bits
4956                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4957                                         if (!(permutation & j))
4958                                                 continue;
4959                                         permutation -= j;
4960                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4961                                         if (!r_hlsl_permutation->compiled)
4962                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4963                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4964                                                 break;
4965                                 }
4966                                 if (i >= SHADERPERMUTATION_COUNT)
4967                                 {
4968                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4969                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4970                                         return; // no bit left to clear, entire mode is broken
4971                                 }
4972                         }
4973                 }
4974                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4975                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4976         }
4977         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4978         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4979         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4980 }
4981 #endif
4982
4983 void R_GLSL_Restart_f(void)
4984 {
4985         unsigned int i, limit;
4986         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4987                 Mem_Free(glslshaderstring);
4988         glslshaderstring = NULL;
4989         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4990                 Mem_Free(cgshaderstring);
4991         cgshaderstring = NULL;
4992         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4993                 Mem_Free(hlslshaderstring);
4994         hlslshaderstring = NULL;
4995         switch(vid.renderpath)
4996         {
4997         case RENDERPATH_D3D9:
4998 #ifdef SUPPORTD3D
4999                 {
5000                         r_hlsl_permutation_t *p;
5001                         r_hlsl_permutation = NULL;
5002 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5003 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5004 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5005 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5006                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5007                         for (i = 0;i < limit;i++)
5008                         {
5009                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5010                                 {
5011                                         if (p->vertexshader)
5012                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5013                                         if (p->pixelshader)
5014                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5015                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5016                                 }
5017                         }
5018                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5019                 }
5020 #endif
5021                 break;
5022         case RENDERPATH_D3D10:
5023                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5024                 break;
5025         case RENDERPATH_D3D11:
5026                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5027                 break;
5028         case RENDERPATH_GL20:
5029                 {
5030                         r_glsl_permutation_t *p;
5031                         r_glsl_permutation = NULL;
5032                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5033                         for (i = 0;i < limit;i++)
5034                         {
5035                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5036                                 {
5037                                         GL_Backend_FreeProgram(p->program);
5038                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5039                                 }
5040                         }
5041                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5042                 }
5043                 break;
5044         case RENDERPATH_CGGL:
5045 #ifdef SUPPORTCG
5046                 {
5047                         r_cg_permutation_t *p;
5048                         r_cg_permutation = NULL;
5049                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5050                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5051                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5052                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5053                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5054                         for (i = 0;i < limit;i++)
5055                         {
5056                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5057                                 {
5058                                         if (p->vprogram)
5059                                                 cgDestroyProgram(p->vprogram);
5060                                         if (p->fprogram)
5061                                                 cgDestroyProgram(p->fprogram);
5062                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5063                                 }
5064                         }
5065                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5066                 }
5067 #endif
5068                 break;
5069         case RENDERPATH_GL13:
5070         case RENDERPATH_GL11:
5071                 break;
5072         }
5073 }
5074
5075 void R_GLSL_DumpShader_f(void)
5076 {
5077         int i;
5078         qfile_t *file;
5079
5080         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5081         if (file)
5082         {
5083                 FS_Print(file, "/* The engine may define the following macros:\n");
5084                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5085                 for (i = 0;i < SHADERMODE_COUNT;i++)
5086                         FS_Print(file, glslshadermodeinfo[i].pretext);
5087                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5088                         FS_Print(file, shaderpermutationinfo[i].pretext);
5089                 FS_Print(file, "*/\n");
5090                 FS_Print(file, builtinshaderstring);
5091                 FS_Close(file);
5092                 Con_Printf("glsl/default.glsl written\n");
5093         }
5094         else
5095                 Con_Printf("failed to write to glsl/default.glsl\n");
5096
5097 #ifdef SUPPORTCG
5098         file = FS_OpenRealFile("cg/default.cg", "w", false);
5099         if (file)
5100         {
5101                 FS_Print(file, "/* The engine may define the following macros:\n");
5102                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5103                 for (i = 0;i < SHADERMODE_COUNT;i++)
5104                         FS_Print(file, cgshadermodeinfo[i].pretext);
5105                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5106                         FS_Print(file, shaderpermutationinfo[i].pretext);
5107                 FS_Print(file, "*/\n");
5108                 FS_Print(file, builtincgshaderstring);
5109                 FS_Close(file);
5110                 Con_Printf("cg/default.cg written\n");
5111         }
5112         else
5113                 Con_Printf("failed to write to cg/default.cg\n");
5114 #endif
5115
5116 #ifdef SUPPORTD3D
5117         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5118         if (file)
5119         {
5120                 FS_Print(file, "/* The engine may define the following macros:\n");
5121                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5122                 for (i = 0;i < SHADERMODE_COUNT;i++)
5123                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5124                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5125                         FS_Print(file, shaderpermutationinfo[i].pretext);
5126                 FS_Print(file, "*/\n");
5127                 FS_Print(file, builtincgshaderstring);
5128                 FS_Close(file);
5129                 Con_Printf("hlsl/default.hlsl written\n");
5130         }
5131         else
5132                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5133 #endif
5134 }
5135
5136 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5137 {
5138         if (!second)
5139                 texturemode = GL_MODULATE;
5140         switch (vid.renderpath)
5141         {
5142         case RENDERPATH_D3D9:
5143 #ifdef SUPPORTD3D
5144                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5145                 R_Mesh_TexBind(GL20TU_FIRST , first );
5146                 R_Mesh_TexBind(GL20TU_SECOND, second);
5147 #endif
5148                 break;
5149         case RENDERPATH_D3D10:
5150                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5151                 break;
5152         case RENDERPATH_D3D11:
5153                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5154                 break;
5155         case RENDERPATH_GL20:
5156                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5157                 R_Mesh_TexBind(GL20TU_FIRST , first );
5158                 R_Mesh_TexBind(GL20TU_SECOND, second);
5159                 break;
5160         case RENDERPATH_CGGL:
5161 #ifdef SUPPORTCG
5162                 CHECKCGERROR
5163                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5164                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5165                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5166 #endif
5167                 break;
5168         case RENDERPATH_GL13:
5169                 R_Mesh_TexBind(0, first );
5170                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5171                 R_Mesh_TexBind(1, second);
5172                 if (second)
5173                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5174                 break;
5175         case RENDERPATH_GL11:
5176                 R_Mesh_TexBind(0, first );
5177                 break;
5178         }
5179 }
5180
5181 void R_SetupShader_DepthOrShadow(void)
5182 {
5183         switch (vid.renderpath)
5184         {
5185         case RENDERPATH_D3D9:
5186 #ifdef SUPPORTD3D
5187                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5188 #endif
5189                 break;
5190         case RENDERPATH_D3D10:
5191                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5192                 break;
5193         case RENDERPATH_D3D11:
5194                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5195                 break;
5196         case RENDERPATH_GL20:
5197                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5198                 break;
5199         case RENDERPATH_CGGL:
5200 #ifdef SUPPORTCG
5201                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5202 #endif
5203                 break;
5204         case RENDERPATH_GL13:
5205                 R_Mesh_TexBind(0, 0);
5206                 R_Mesh_TexBind(1, 0);
5207                 break;
5208         case RENDERPATH_GL11:
5209                 R_Mesh_TexBind(0, 0);
5210                 break;
5211         }
5212 }
5213
5214 void R_SetupShader_ShowDepth(void)
5215 {
5216         switch (vid.renderpath)
5217         {
5218         case RENDERPATH_D3D9:
5219 #ifdef SUPPORTHLSL
5220                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5221 #endif
5222                 break;
5223         case RENDERPATH_D3D10:
5224                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5225                 break;
5226         case RENDERPATH_D3D11:
5227                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5228                 break;
5229         case RENDERPATH_GL20:
5230                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5231                 break;
5232         case RENDERPATH_CGGL:
5233 #ifdef SUPPORTCG
5234                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5235 #endif
5236                 break;
5237         case RENDERPATH_GL13:
5238                 break;
5239         case RENDERPATH_GL11:
5240                 break;
5241         }
5242 }
5243
5244 extern qboolean r_shadow_usingdeferredprepass;
5245 extern cvar_t r_shadow_deferred_8bitrange;
5246 extern rtexture_t *r_shadow_attenuationgradienttexture;
5247 extern rtexture_t *r_shadow_attenuation2dtexture;
5248 extern rtexture_t *r_shadow_attenuation3dtexture;
5249 extern qboolean r_shadow_usingshadowmap2d;
5250 extern qboolean r_shadow_usingshadowmaportho;
5251 extern float r_shadow_shadowmap_texturescale[2];
5252 extern float r_shadow_shadowmap_parameters[4];
5253 extern qboolean r_shadow_shadowmapvsdct;
5254 extern qboolean r_shadow_shadowmapsampler;
5255 extern int r_shadow_shadowmappcf;
5256 extern rtexture_t *r_shadow_shadowmap2dtexture;
5257 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5258 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5259 extern matrix4x4_t r_shadow_shadowmapmatrix;
5260 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5261 extern int r_shadow_prepass_width;
5262 extern int r_shadow_prepass_height;
5263 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5264 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5265 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5266 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5267 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5268 extern cvar_t gl_mesh_separatearrays;
5269 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5270 {
5271         // a blendfunc allows colormod if:
5272         // a) it can never keep the destination pixel invariant, or
5273         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5274         // this is to prevent unintended side effects from colormod
5275
5276         // in formulas:
5277         // IF there is a (s, sa) for which for all (d, da),
5278         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5279         // THEN, for this (s, sa) and all (colormod, d, da):
5280         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5281         // OBVIOUSLY, this means that
5282         //   s*colormod * src(s*colormod, d, sa, da) = 0
5283         //   dst(s*colormod, d, sa, da)              = 1
5284
5285         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5286
5287         // main condition to leave dst color invariant:
5288         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5289         //   src == GL_ZERO:
5290         //     s * 0 + d * dst(s, d, sa, da) == d
5291         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5292         //       => colormod is a problem for GL_SRC_COLOR only
5293         //   src == GL_ONE:
5294         //     s + d * dst(s, d, sa, da) == d
5295         //       => s == 0
5296         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5297         //       => colormod is never problematic for these
5298         //   src == GL_SRC_COLOR:
5299         //     s*s + d * dst(s, d, sa, da) == d
5300         //       => s == 0
5301         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is never problematic for these
5303         //   src == GL_ONE_MINUS_SRC_COLOR:
5304         //     s*(1-s) + d * dst(s, d, sa, da) == d
5305         //       => s == 0 or s == 1
5306         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod is a problem for GL_SRC_COLOR only
5308         //   src == GL_DST_COLOR
5309         //     s*d + d * dst(s, d, sa, da) == d
5310         //       => s == 1
5311         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312         //       => colormod is always a problem
5313         //     or
5314         //       => s == 0
5315         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is never problematic for these
5317         //       => BUT, we do not know s! We must assume it is problematic
5318         //       then... except in GL_ONE case, where we know all invariant
5319         //       cases are fine
5320         //   src == GL_ONE_MINUS_DST_COLOR
5321         //     s*(1-d) + d * dst(s, d, sa, da) == d
5322         //       => s == 0 (1-d is impossible to handle for our desired result)
5323         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5324         //       => colormod is never problematic for these
5325         //   src == GL_SRC_ALPHA
5326         //     s*sa + d * dst(s, d, sa, da) == d
5327         //       => s == 0, or sa == 0
5328         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5329         //       => colormod breaks in the case GL_SRC_COLOR only
5330         //   src == GL_ONE_MINUS_SRC_ALPHA
5331         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5332         //       => s == 0, or sa == 1
5333         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334         //       => colormod breaks in the case GL_SRC_COLOR only
5335         //   src == GL_DST_ALPHA
5336         //     s*da + d * dst(s, d, sa, da) == d
5337         //       => s == 0
5338         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5339         //       => colormod is never problematic for these
5340
5341         switch(src)
5342         {
5343                 case GL_ZERO:
5344                 case GL_ONE_MINUS_SRC_COLOR:
5345                 case GL_SRC_ALPHA:
5346                 case GL_ONE_MINUS_SRC_ALPHA:
5347                         if(dst == GL_SRC_COLOR)
5348                                 return false;
5349                         return true;
5350                 case GL_ONE:
5351                 case GL_SRC_COLOR:
5352                 case GL_ONE_MINUS_DST_COLOR:
5353                 case GL_DST_ALPHA:
5354                 case GL_ONE_MINUS_DST_ALPHA:
5355                         return true;
5356                 case GL_DST_COLOR:
5357                         if(dst == GL_ONE)
5358                                 return true;
5359                         return false;
5360                 default:
5361                         return false;
5362         }
5363 }
5364 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5365 {
5366         // select a permutation of the lighting shader appropriate to this
5367         // combination of texture, entity, light source, and fogging, only use the
5368         // minimum features necessary to avoid wasting rendering time in the
5369         // fragment shader on features that are not being used
5370         unsigned int permutation = 0;
5371         unsigned int mode = 0;
5372         qboolean allow_colormod;
5373         static float dummy_colormod[3] = {1, 1, 1};
5374         float *colormod = rsurface.colormod;
5375         float m16f[16];
5376         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5377         if (rsurfacepass == RSURFPASS_BACKGROUND)
5378         {
5379                 // distorted background
5380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5381                 {
5382                         mode = SHADERMODE_WATER;
5383                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5384                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5385                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5386                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5387                 }
5388                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5389                 {
5390                         mode = SHADERMODE_REFRACTION;
5391                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5393                 }
5394                 else
5395                 {
5396                         mode = SHADERMODE_GENERIC;
5397                         permutation |= SHADERPERMUTATION_DIFFUSE;
5398                         GL_BlendFunc(GL_ONE, GL_ZERO);
5399                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5400                 }
5401                 GL_AlphaTest(false);
5402         }
5403         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5404         {
5405                 if (r_glsl_offsetmapping.integer)
5406                 {
5407                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5408                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5409                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5410                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5411                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5412                         {
5413                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5415                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416                         }
5417                 }
5418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5419                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5421                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5422                 // normalmap (deferred prepass), may use alpha test on diffuse
5423                 mode = SHADERMODE_DEFERREDGEOMETRY;
5424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5425                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5426                 GL_AlphaTest(false);
5427                 GL_BlendFunc(GL_ONE, GL_ZERO);
5428                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5429         }
5430         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5431         {
5432                 if (r_glsl_offsetmapping.integer)
5433                 {
5434                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5435                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5436                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5437                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5438                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5439                         {
5440                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5441                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5442                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5443                         }
5444                 }
5445                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5446                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5447                 // light source
5448                 mode = SHADERMODE_LIGHTSOURCE;
5449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5450                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5451                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5452                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5453                 if (diffusescale > 0)
5454                         permutation |= SHADERPERMUTATION_DIFFUSE;
5455                 if (specularscale > 0)
5456                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5457                 if (r_refdef.fogenabled)
5458                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5459                 if (rsurface.texture->colormapping)
5460                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5461                 if (r_shadow_usingshadowmap2d)
5462                 {
5463                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5464                         if(r_shadow_shadowmapvsdct)
5465                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5466
5467                         if (r_shadow_shadowmapsampler)
5468                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5469                         if (r_shadow_shadowmappcf > 1)
5470                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5471                         else if (r_shadow_shadowmappcf)
5472                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5473                 }
5474                 if (rsurface.texture->reflectmasktexture)
5475                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5476                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5477                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5478                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5479         }
5480         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5481         {
5482                 if (r_glsl_offsetmapping.integer)
5483                 {
5484                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5485                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5486                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5487                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5488                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5489                         {
5490                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5491                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5492                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5493                         }
5494                 }
5495                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5496                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5497                 // unshaded geometry (fullbright or ambient model lighting)
5498                 mode = SHADERMODE_FLATCOLOR;
5499                 ambientscale = diffusescale = specularscale = 0;
5500                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5501                         permutation |= SHADERPERMUTATION_GLOW;
5502                 if (r_refdef.fogenabled)
5503                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5504                 if (rsurface.texture->colormapping)
5505                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5506                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5507                 {
5508                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5509                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5510
5511                         if (r_shadow_shadowmapsampler)
5512                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5513                         if (r_shadow_shadowmappcf > 1)
5514                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5515                         else if (r_shadow_shadowmappcf)
5516                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5517                 }
5518                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5519                         permutation |= SHADERPERMUTATION_REFLECTION;
5520                 if (rsurface.texture->reflectmasktexture)
5521                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5522                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5523                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5524                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5525         }
5526         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5527         {
5528                 if (r_glsl_offsetmapping.integer)
5529                 {
5530                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5531                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5532                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5533                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5534                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5535                         {
5536                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5537                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5538                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5539                         }
5540                 }
5541                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5542                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5543                 // directional model lighting
5544                 mode = SHADERMODE_LIGHTDIRECTION;
5545                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5546                         permutation |= SHADERPERMUTATION_GLOW;
5547                 permutation |= SHADERPERMUTATION_DIFFUSE;
5548                 if (specularscale > 0)
5549                         permutation |= SHADERPERMUTATION_SPECULAR;
5550                 if (r_refdef.fogenabled)
5551                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5552                 if (rsurface.texture->colormapping)
5553                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5554                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5555                 {
5556                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5557                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5558
5559                         if (r_shadow_shadowmapsampler)
5560                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5561                         if (r_shadow_shadowmappcf > 1)
5562                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5563                         else if (r_shadow_shadowmappcf)
5564                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5565                 }
5566                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5567                         permutation |= SHADERPERMUTATION_REFLECTION;
5568                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5569                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5570                 if (rsurface.texture->reflectmasktexture)
5571                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5572                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5573                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5574                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5575         }
5576         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5577         {
5578                 if (r_glsl_offsetmapping.integer)
5579                 {
5580                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5581                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5582                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5583                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5584                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5585                         {
5586                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5587                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5588                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5589                         }
5590                 }
5591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5592                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5593                 // ambient model lighting
5594                 mode = SHADERMODE_LIGHTDIRECTION;
5595                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5596                         permutation |= SHADERPERMUTATION_GLOW;
5597                 if (r_refdef.fogenabled)
5598                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5599                 if (rsurface.texture->colormapping)
5600                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5601                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5602                 {
5603                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5604                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5605
5606                         if (r_shadow_shadowmapsampler)
5607                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608                         if (r_shadow_shadowmappcf > 1)
5609                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610                         else if (r_shadow_shadowmappcf)
5611                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5612                 }
5613                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5614                         permutation |= SHADERPERMUTATION_REFLECTION;
5615                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5616                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5617                 if (rsurface.texture->reflectmasktexture)
5618                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5619                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5620                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5622         }
5623         else
5624         {
5625                 if (r_glsl_offsetmapping.integer)
5626                 {
5627                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5628                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5629                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5630                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5631                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5632                         {
5633                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5634                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5635                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5636                         }
5637                 }
5638                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5639                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5640                 // lightmapped wall
5641                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5642                         permutation |= SHADERPERMUTATION_GLOW;
5643                 if (r_refdef.fogenabled)
5644                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5645                 if (rsurface.texture->colormapping)
5646                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5647                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5648                 {
5649                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5650                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5651
5652                         if (r_shadow_shadowmapsampler)
5653                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5654                         if (r_shadow_shadowmappcf > 1)
5655                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5656                         else if (r_shadow_shadowmappcf)
5657                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5658                 }
5659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5660                         permutation |= SHADERPERMUTATION_REFLECTION;
5661                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5662                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5663                 if (rsurface.texture->reflectmasktexture)
5664                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5665                 if (FAKELIGHT_ENABLED)
5666                 {
5667                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5668                         mode = SHADERMODE_FAKELIGHT;
5669                         permutation |= SHADERPERMUTATION_DIFFUSE;
5670                         if (specularscale > 0)
5671                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5672                 }
5673                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5674                 {
5675                         // deluxemapping (light direction texture)
5676                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5677                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5678                         else
5679                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5680                         permutation |= SHADERPERMUTATION_DIFFUSE;
5681                         if (specularscale > 0)
5682                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5683                 }
5684                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5685                 {
5686                         // fake deluxemapping (uniform light direction in tangentspace)
5687                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5688                         permutation |= SHADERPERMUTATION_DIFFUSE;
5689                         if (specularscale > 0)
5690                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5691                 }
5692                 else if (rsurface.uselightmaptexture)
5693                 {
5694                         // ordinary lightmapping (q1bsp, q3bsp)
5695                         mode = SHADERMODE_LIGHTMAP;
5696                 }
5697                 else
5698                 {
5699                         // ordinary vertex coloring (q3bsp)
5700                         mode = SHADERMODE_VERTEXCOLOR;
5701                 }
5702                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5703                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5704                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5705         }
5706         if(!allow_colormod)
5707                 colormod = dummy_colormod;
5708         switch(vid.renderpath)
5709         {
5710         case RENDERPATH_D3D9:
5711 #ifdef SUPPORTD3D
5712                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5713                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5714                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5715                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5716                 if (mode == SHADERMODE_LIGHTSOURCE)
5717                 {
5718                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5719                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5720                 }
5721                 else
5722                 {
5723                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5724                         {
5725                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5726                         }
5727                 }
5728                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5729                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5730                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5731                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5732                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5733
5734                 if (mode == SHADERMODE_LIGHTSOURCE)
5735                 {
5736                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5737                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5738                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5739                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5740                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5741
5742                         // additive passes are only darkened by fog, not tinted
5743                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5744                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5745                 }
5746                 else
5747                 {
5748                         if (mode == SHADERMODE_FLATCOLOR)
5749                         {
5750                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5751                         }
5752                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5753                         {
5754                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5755                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5756                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5757                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5759                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5760                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5761                         }
5762                         else
5763                         {
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5766                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5767                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5769                         }
5770                         // additive passes are only darkened by fog, not tinted
5771                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5772                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5773                         else
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5775                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5776                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5777                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5778                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5779                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5780                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5781                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5782                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5783                         if (mode == SHADERMODE_WATER)
5784                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5785                 }
5786                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5787                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5788                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5789                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5790                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5791                 if (rsurface.texture->pantstexture)
5792                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5793                 else
5794                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5795                 if (rsurface.texture->shirttexture)
5796                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5797                 else
5798                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5799                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5800                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5801                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5802                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5803                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5804                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5805                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5806
5807                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5808                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5809                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5810                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5811                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5812                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5813                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5814                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5815                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5816                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5817                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5818                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5819                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5820                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5821                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5822                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5823                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5824                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5825                 {
5826                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5827                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5828                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5829                 }
5830                 else
5831                 {
5832                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5833                 }
5834 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5835 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5836                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5837                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5838                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5839                 {
5840                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5841                         if (rsurface.rtlight)
5842                         {
5843                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5844                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5845                         }
5846                 }
5847 #endif
5848                 break;
5849         case RENDERPATH_D3D10:
5850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5851                 break;
5852         case RENDERPATH_D3D11:
5853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5854                 break;
5855         case RENDERPATH_GL20:
5856                 if (gl_mesh_separatearrays.integer)
5857                 {
5858                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5859                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5860                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5861                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5862                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5863                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5864                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5865                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5866                 }
5867                 else
5868                 {
5869                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5870                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5871                 }
5872                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5873                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5874                 if (mode == SHADERMODE_LIGHTSOURCE)
5875                 {
5876                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5877                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5878                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5879                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5880                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5881                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5882         
5883                         // additive passes are only darkened by fog, not tinted
5884                         if (r_glsl_permutation->loc_FogColor >= 0)
5885                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5886                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5887                 }
5888                 else
5889                 {
5890                         if (mode == SHADERMODE_FLATCOLOR)
5891                         {
5892                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5893                         }
5894                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5895                         {
5896                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5897                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5898                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5899                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5900                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5901                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5902                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5903                         }
5904                         else
5905                         {
5906                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5907                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5908                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5909                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5910                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5911                         }
5912                         // additive passes are only darkened by fog, not tinted
5913                         if (r_glsl_permutation->loc_FogColor >= 0)
5914                         {
5915                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5916                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5917                                 else
5918                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5919                         }
5920                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5921                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5922                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5923                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5924                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5925                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5926                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5927                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5928                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5929                 }
5930                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5931                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5932                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5933                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5934                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5935
5936                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5937                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5938                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5939                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5940                 {
5941                         if (rsurface.texture->pantstexture)
5942                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5943                         else
5944                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5945                 }
5946                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5947                 {
5948                         if (rsurface.texture->shirttexture)
5949                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5950                         else
5951                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5952                 }
5953                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5954                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5955                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5956                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5957                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5958                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5959                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5960
5961         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5962         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5963         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5964                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5965                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5966                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5967                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5968                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5969                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5970                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5971                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5972                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5973                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5974                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5975                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5976                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5977                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5978                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5979                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5980                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5981                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5982                 {
5983                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5984                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5985                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5986                 }
5987                 else
5988                 {
5989                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5990                 }
5991 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5992 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5993                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5994                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5995                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5996                 {
5997                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5998                         if (rsurface.rtlight)
5999                         {
6000                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6001                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6002                         }
6003                 }
6004                 CHECKGLERROR
6005                 break;
6006         case RENDERPATH_CGGL:
6007 #ifdef SUPPORTCG
6008                 if (gl_mesh_separatearrays.integer)
6009                 {
6010                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6011                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6012                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6013                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6014                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6015                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6016                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6017                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6018                 }
6019                 else
6020                 {
6021                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6022                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6023                 }
6024                 R_SetupShader_SetPermutationCG(mode, permutation);
6025                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6026                 if (mode == SHADERMODE_LIGHTSOURCE)
6027                 {
6028                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6029                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6030                 }
6031                 else
6032                 {
6033                         if (mode == SHADERMODE_LIGHTDIRECTION)
6034                         {
6035                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6036                         }
6037                 }
6038                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6039                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6040                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6041                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6042                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6043                 CHECKGLERROR
6044
6045                 if (mode == SHADERMODE_LIGHTSOURCE)
6046                 {
6047                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6048                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6049                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6050                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6051                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
6052
6053                         // additive passes are only darkened by fog, not tinted
6054                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6055                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6056                 }
6057                 else
6058                 {
6059                         if (mode == SHADERMODE_FLATCOLOR)
6060                         {
6061                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6062                         }
6063                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6064                         {
6065                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6066                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6067                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6068                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6069                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6070                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
6071                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6072                         }
6073                         else
6074                         {
6075                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6076                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
6077                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6078                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6079                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6080                         }
6081                         // additive passes are only darkened by fog, not tinted
6082                         if (r_cg_permutation->fp_FogColor)
6083                         {
6084                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6085                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6086                                 else
6087                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6088                                 CHECKCGERROR
6089                         }
6090                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
6091                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
6092                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
6093                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6094                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6095                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6096                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6097                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6098                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6099                 }
6100                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6101                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6102                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6103                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6104                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6105                 if (r_cg_permutation->fp_Color_Pants)
6106                 {
6107                         if (rsurface.texture->pantstexture)
6108                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6109                         else
6110                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6111                         CHECKCGERROR
6112                 }
6113                 if (r_cg_permutation->fp_Color_Shirt)
6114                 {
6115                         if (rsurface.texture->shirttexture)
6116                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6117                         else
6118                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6119                         CHECKCGERROR
6120                 }
6121                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6122                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6123                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6124                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6125                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6126                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6127                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6128
6129         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6130         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6131         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6133                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6134                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6135                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6136                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6137                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6139                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6140                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6149                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6150                 {
6151                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6152                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6153                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6154                 }
6155                 else
6156                 {
6157                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6158                 }
6159                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6161                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6162                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6163                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6164                 {
6165                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6166                         if (rsurface.rtlight)
6167                         {
6168                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6169                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6170                         }
6171                 }
6172
6173                 CHECKGLERROR
6174 #endif
6175                 break;
6176         case RENDERPATH_GL13:
6177         case RENDERPATH_GL11:
6178                 break;
6179         }
6180 }
6181
6182 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6183 {
6184         // select a permutation of the lighting shader appropriate to this
6185         // combination of texture, entity, light source, and fogging, only use the
6186         // minimum features necessary to avoid wasting rendering time in the
6187         // fragment shader on features that are not being used
6188         unsigned int permutation = 0;
6189         unsigned int mode = 0;
6190         const float *lightcolorbase = rtlight->currentcolor;
6191         float ambientscale = rtlight->ambientscale;
6192         float diffusescale = rtlight->diffusescale;
6193         float specularscale = rtlight->specularscale;
6194         // this is the location of the light in view space
6195         vec3_t viewlightorigin;
6196         // this transforms from view space (camera) to light space (cubemap)
6197         matrix4x4_t viewtolight;
6198         matrix4x4_t lighttoview;
6199         float viewtolight16f[16];
6200         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6201         // light source
6202         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6203         if (rtlight->currentcubemap != r_texture_whitecube)
6204                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6205         if (diffusescale > 0)
6206                 permutation |= SHADERPERMUTATION_DIFFUSE;
6207         if (specularscale > 0)
6208                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6209         if (r_shadow_usingshadowmap2d)
6210         {
6211                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6212                 if (r_shadow_shadowmapvsdct)
6213                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6214
6215                 if (r_shadow_shadowmapsampler)
6216                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6217                 if (r_shadow_shadowmappcf > 1)
6218                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6219                 else if (r_shadow_shadowmappcf)
6220                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6221         }
6222         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6223         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6224         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6225         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6226         switch(vid.renderpath)
6227         {
6228         case RENDERPATH_D3D9:
6229 #ifdef SUPPORTD3D
6230                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6231                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6232                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6233                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6234                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6235                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6236                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6237                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6238                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6239                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6240                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6241
6242                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6243                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6244                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6245                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6246                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6247                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6248 #endif
6249                 break;
6250         case RENDERPATH_D3D10:
6251                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6252                 break;
6253         case RENDERPATH_D3D11:
6254                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6255                 break;
6256         case RENDERPATH_GL20:
6257                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6258                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6259                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6260                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6261                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6262                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6263                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6264                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6265                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6266                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6267                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6268
6269                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6270                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6271                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6272                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6273                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6274                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6275                 break;
6276         case RENDERPATH_CGGL:
6277 #ifdef SUPPORTCG
6278                 R_SetupShader_SetPermutationCG(mode, permutation);
6279                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6280                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6281                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
6282                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
6283                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6284                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6285                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6286                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6287                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6288                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6289
6290                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6291                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6292                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6293                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6294                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6295                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6296 #endif
6297                 break;
6298         case RENDERPATH_GL13:
6299         case RENDERPATH_GL11:
6300                 break;
6301         }
6302 }
6303
6304 #define SKINFRAME_HASH 1024
6305
6306 typedef struct
6307 {
6308         int loadsequence; // incremented each level change
6309         memexpandablearray_t array;
6310         skinframe_t *hash[SKINFRAME_HASH];
6311 }
6312 r_skinframe_t;
6313 r_skinframe_t r_skinframe;
6314
6315 void R_SkinFrame_PrepareForPurge(void)
6316 {
6317         r_skinframe.loadsequence++;
6318         // wrap it without hitting zero
6319         if (r_skinframe.loadsequence >= 200)
6320                 r_skinframe.loadsequence = 1;
6321 }
6322
6323 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6324 {
6325         if (!skinframe)
6326                 return;
6327         // mark the skinframe as used for the purging code
6328         skinframe->loadsequence = r_skinframe.loadsequence;
6329 }
6330
6331 void R_SkinFrame_Purge(void)
6332 {
6333         int i;
6334         skinframe_t *s;
6335         for (i = 0;i < SKINFRAME_HASH;i++)
6336         {
6337                 for (s = r_skinframe.hash[i];s;s = s->next)
6338                 {
6339                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6340                         {
6341                                 if (s->merged == s->base)
6342                                         s->merged = NULL;
6343                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6344                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6345                                 R_PurgeTexture(s->merged);s->merged = NULL;
6346                                 R_PurgeTexture(s->base  );s->base   = NULL;
6347                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6348                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6349                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6350                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6351                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6352                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6353                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6354                                 s->loadsequence = 0;
6355                         }
6356                 }
6357         }
6358 }
6359
6360 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6361         skinframe_t *item;
6362         char basename[MAX_QPATH];
6363
6364         Image_StripImageExtension(name, basename, sizeof(basename));
6365
6366         if( last == NULL ) {
6367                 int hashindex;
6368                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6369                 item = r_skinframe.hash[hashindex];
6370         } else {
6371                 item = last->next;
6372         }
6373
6374         // linearly search through the hash bucket
6375         for( ; item ; item = item->next ) {
6376                 if( !strcmp( item->basename, basename ) ) {
6377                         return item;
6378                 }
6379         }
6380         return NULL;
6381 }
6382
6383 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6384 {
6385         skinframe_t *item;
6386         int hashindex;
6387         char basename[MAX_QPATH];
6388
6389         Image_StripImageExtension(name, basename, sizeof(basename));
6390
6391         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6392         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6393                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6394                         break;
6395
6396         if (!item) {
6397                 rtexture_t *dyntexture;
6398                 // check whether its a dynamic texture
6399                 dyntexture = CL_GetDynTexture( basename );
6400                 if (!add && !dyntexture)
6401                         return NULL;
6402                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6403                 memset(item, 0, sizeof(*item));
6404                 strlcpy(item->basename, basename, sizeof(item->basename));
6405                 item->base = dyntexture; // either NULL or dyntexture handle
6406                 item->textureflags = textureflags;
6407                 item->comparewidth = comparewidth;
6408                 item->compareheight = compareheight;
6409                 item->comparecrc = comparecrc;
6410                 item->next = r_skinframe.hash[hashindex];
6411                 r_skinframe.hash[hashindex] = item;
6412         }
6413         else if( item->base == NULL )
6414         {
6415                 rtexture_t *dyntexture;
6416                 // check whether its a dynamic texture
6417                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
6418                 dyntexture = CL_GetDynTexture( basename );
6419                 item->base = dyntexture; // either NULL or dyntexture handle
6420         }
6421
6422         R_SkinFrame_MarkUsed(item);
6423         return item;
6424 }
6425
6426 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6427         { \
6428                 unsigned long long avgcolor[5], wsum; \
6429                 int pix, comp, w; \
6430                 avgcolor[0] = 0; \
6431                 avgcolor[1] = 0; \
6432                 avgcolor[2] = 0; \
6433                 avgcolor[3] = 0; \
6434                 avgcolor[4] = 0; \
6435                 wsum = 0; \
6436                 for(pix = 0; pix < cnt; ++pix) \
6437                 { \
6438                         w = 0; \
6439                         for(comp = 0; comp < 3; ++comp) \
6440                                 w += getpixel; \
6441                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6442                         { \
6443                                 ++wsum; \
6444                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6445                                 w = getpixel; \
6446                                 for(comp = 0; comp < 3; ++comp) \
6447                                         avgcolor[comp] += getpixel * w; \
6448                                 avgcolor[3] += w; \
6449                         } \
6450                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6451                         avgcolor[4] += getpixel; \
6452                 } \
6453                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6454                         avgcolor[3] = 1; \
6455                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6456                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6457                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6458                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6459         }
6460
6461 extern cvar_t gl_picmip;
6462 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6463 {
6464         int j;
6465         unsigned char *pixels;
6466         unsigned char *bumppixels;
6467         unsigned char *basepixels = NULL;
6468         int basepixels_width = 0;
6469         int basepixels_height = 0;
6470         skinframe_t *skinframe;
6471         rtexture_t *ddsbase = NULL;
6472         qboolean ddshasalpha = false;
6473         float ddsavgcolor[4];
6474         char basename[MAX_QPATH];
6475         int miplevel = R_PicmipForFlags(textureflags);
6476         int savemiplevel = miplevel;
6477         int mymiplevel;
6478
6479         if (cls.state == ca_dedicated)
6480                 return NULL;
6481
6482         // return an existing skinframe if already loaded
6483         // if loading of the first image fails, don't make a new skinframe as it
6484         // would cause all future lookups of this to be missing
6485         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6486         if (skinframe && skinframe->base)
6487                 return skinframe;
6488
6489         Image_StripImageExtension(name, basename, sizeof(basename));
6490
6491         // check for DDS texture file first
6492         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6493         {
6494                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6495                 if (basepixels == NULL)
6496                         return NULL;
6497         }
6498
6499         // FIXME handle miplevel
6500
6501         if (developer_loading.integer)
6502                 Con_Printf("loading skin \"%s\"\n", name);
6503
6504         // we've got some pixels to store, so really allocate this new texture now
6505         if (!skinframe)
6506                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6507         skinframe->stain = NULL;
6508         skinframe->merged = NULL;
6509         skinframe->base = NULL;
6510         skinframe->pants = NULL;
6511         skinframe->shirt = NULL;
6512         skinframe->nmap = NULL;
6513         skinframe->gloss = NULL;
6514         skinframe->glow = NULL;
6515         skinframe->fog = NULL;
6516         skinframe->reflect = NULL;
6517         skinframe->hasalpha = false;
6518
6519         if (ddsbase)
6520         {
6521                 skinframe->base = ddsbase;
6522                 skinframe->hasalpha = ddshasalpha;
6523                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6524                 if (r_loadfog && skinframe->hasalpha)
6525                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6526                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6527         }
6528         else
6529         {
6530                 basepixels_width = image_width;
6531                 basepixels_height = image_height;
6532                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6533                 if (textureflags & TEXF_ALPHA)
6534                 {
6535                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6536                         {
6537                                 if (basepixels[j] < 255)
6538                                 {
6539                                         skinframe->hasalpha = true;
6540                                         break;
6541                                 }
6542                         }
6543                         if (r_loadfog && skinframe->hasalpha)
6544                         {
6545                                 // has transparent pixels
6546                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6547                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6548                                 {
6549                                         pixels[j+0] = 255;
6550                                         pixels[j+1] = 255;
6551                                         pixels[j+2] = 255;
6552                                         pixels[j+3] = basepixels[j+3];
6553                                 }
6554                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6555                                 Mem_Free(pixels);
6556                         }
6557                 }
6558                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6559                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6560                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6561                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6562                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6563                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6564         }
6565
6566         if (r_loaddds)
6567         {
6568                 mymiplevel = savemiplevel;
6569                 if (r_loadnormalmap)
6570                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6571                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6572                 if (r_loadgloss)
6573                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6577         }
6578
6579         // _norm is the name used by tenebrae and has been adopted as standard
6580         if (r_loadnormalmap && skinframe->nmap == NULL)
6581         {
6582                 mymiplevel = savemiplevel;
6583                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6584                 {
6585                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6586                         Mem_Free(pixels);
6587                         pixels = NULL;
6588                 }
6589                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6590                 {
6591                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6592                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6593                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6594                         Mem_Free(pixels);
6595                         Mem_Free(bumppixels);
6596                 }
6597                 else if (r_shadow_bumpscale_basetexture.value > 0)
6598                 {
6599                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6600                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6601                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6602                         Mem_Free(pixels);
6603                 }
6604                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6605                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6606         }
6607
6608         // _luma is supported only for tenebrae compatibility
6609         // _glow is the preferred name
6610         mymiplevel = savemiplevel;
6611         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6612         {
6613                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6614                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6615                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6616                 Mem_Free(pixels);pixels = NULL;
6617         }
6618
6619         mymiplevel = savemiplevel;
6620         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6621         {
6622                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6624                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6625                 Mem_Free(pixels);
6626                 pixels = NULL;
6627         }
6628
6629         mymiplevel = savemiplevel;
6630         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6631         {
6632                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6633                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6634                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6635                 Mem_Free(pixels);
6636                 pixels = NULL;
6637         }
6638
6639         mymiplevel = savemiplevel;
6640         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641         {
6642                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6643                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6644                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6645                 Mem_Free(pixels);
6646                 pixels = NULL;
6647         }
6648
6649         mymiplevel = savemiplevel;
6650         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651         {
6652                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6654                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6655                 Mem_Free(pixels);
6656                 pixels = NULL;
6657         }
6658
6659         if (basepixels)
6660                 Mem_Free(basepixels);
6661
6662         return skinframe;
6663 }
6664
6665 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6666 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6667 {
6668         int i;
6669         unsigned char *temp1, *temp2;
6670         skinframe_t *skinframe;
6671
6672         if (cls.state == ca_dedicated)
6673                 return NULL;
6674
6675         // if already loaded just return it, otherwise make a new skinframe
6676         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6677         if (skinframe && skinframe->base)
6678                 return skinframe;
6679
6680         skinframe->stain = NULL;
6681         skinframe->merged = NULL;
6682         skinframe->base = NULL;
6683         skinframe->pants = NULL;
6684         skinframe->shirt = NULL;
6685         skinframe->nmap = NULL;
6686         skinframe->gloss = NULL;
6687         skinframe->glow = NULL;
6688         skinframe->fog = NULL;
6689         skinframe->reflect = NULL;
6690         skinframe->hasalpha = false;
6691
6692         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6693         if (!skindata)
6694                 return NULL;
6695
6696         if (developer_loading.integer)
6697                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6698
6699         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6700         {
6701                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6702                 temp2 = temp1 + width * height * 4;
6703                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6704                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6705                 Mem_Free(temp1);
6706         }
6707         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6708         if (textureflags & TEXF_ALPHA)
6709         {
6710                 for (i = 3;i < width * height * 4;i += 4)
6711                 {
6712                         if (skindata[i] < 255)
6713                         {
6714                                 skinframe->hasalpha = true;
6715                                 break;
6716                         }
6717                 }
6718                 if (r_loadfog && skinframe->hasalpha)
6719                 {
6720                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6721                         memcpy(fogpixels, skindata, width * height * 4);
6722                         for (i = 0;i < width * height * 4;i += 4)
6723                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6724                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6725                         Mem_Free(fogpixels);
6726                 }
6727         }
6728
6729         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6730         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6731
6732         return skinframe;
6733 }
6734
6735 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6736 {
6737         int i;
6738         int featuresmask;
6739         skinframe_t *skinframe;
6740
6741         if (cls.state == ca_dedicated)
6742                 return NULL;
6743
6744         // if already loaded just return it, otherwise make a new skinframe
6745         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6746         if (skinframe && skinframe->base)
6747                 return skinframe;
6748
6749         skinframe->stain = NULL;
6750         skinframe->merged = NULL;
6751         skinframe->base = NULL;
6752         skinframe->pants = NULL;
6753         skinframe->shirt = NULL;
6754         skinframe->nmap = NULL;
6755         skinframe->gloss = NULL;
6756         skinframe->glow = NULL;
6757         skinframe->fog = NULL;
6758         skinframe->reflect = NULL;
6759         skinframe->hasalpha = false;
6760
6761         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6762         if (!skindata)
6763                 return NULL;
6764
6765         if (developer_loading.integer)
6766                 Con_Printf("loading quake skin \"%s\"\n", name);
6767
6768         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6769         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6770         memcpy(skinframe->qpixels, skindata, width*height);
6771         skinframe->qwidth = width;
6772         skinframe->qheight = height;
6773
6774         featuresmask = 0;
6775         for (i = 0;i < width * height;i++)
6776                 featuresmask |= palette_featureflags[skindata[i]];
6777
6778         skinframe->hasalpha = false;
6779         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6780         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6781         skinframe->qgeneratemerged = true;
6782         skinframe->qgeneratebase = skinframe->qhascolormapping;
6783         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6784
6785         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6786         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6787
6788         return skinframe;
6789 }
6790
6791 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6792 {
6793         int width;
6794         int height;
6795         unsigned char *skindata;
6796
6797         if (!skinframe->qpixels)
6798                 return;
6799
6800         if (!skinframe->qhascolormapping)
6801                 colormapped = false;
6802
6803         if (colormapped)
6804         {
6805                 if (!skinframe->qgeneratebase)
6806                         return;
6807         }
6808         else
6809         {
6810                 if (!skinframe->qgeneratemerged)
6811                         return;
6812         }
6813
6814         width = skinframe->qwidth;
6815         height = skinframe->qheight;
6816         skindata = skinframe->qpixels;
6817
6818         if (skinframe->qgeneratenmap)
6819         {
6820                 unsigned char *temp1, *temp2;
6821                 skinframe->qgeneratenmap = false;
6822                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6823                 temp2 = temp1 + width * height * 4;
6824                 // use either a custom palette or the quake palette
6825                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6826                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6827                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6828                 Mem_Free(temp1);
6829         }
6830
6831         if (skinframe->qgenerateglow)
6832         {
6833                 skinframe->qgenerateglow = false;
6834                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6835         }
6836
6837         if (colormapped)
6838         {
6839                 skinframe->qgeneratebase = false;
6840                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6841                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6842                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6843         }
6844         else
6845         {
6846                 skinframe->qgeneratemerged = false;
6847                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6848         }
6849
6850         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6851         {
6852                 Mem_Free(skinframe->qpixels);
6853                 skinframe->qpixels = NULL;
6854         }
6855 }
6856
6857 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6858 {
6859         int i;
6860         skinframe_t *skinframe;
6861
6862         if (cls.state == ca_dedicated)
6863                 return NULL;
6864
6865         // if already loaded just return it, otherwise make a new skinframe
6866         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6867         if (skinframe && skinframe->base)
6868                 return skinframe;
6869
6870         skinframe->stain = NULL;
6871         skinframe->merged = NULL;
6872         skinframe->base = NULL;
6873         skinframe->pants = NULL;
6874         skinframe->shirt = NULL;
6875         skinframe->nmap = NULL;
6876         skinframe->gloss = NULL;
6877         skinframe->glow = NULL;
6878         skinframe->fog = NULL;
6879         skinframe->reflect = NULL;
6880         skinframe->hasalpha = false;
6881
6882         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6883         if (!skindata)
6884                 return NULL;
6885
6886         if (developer_loading.integer)
6887                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6888
6889         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6890         if (textureflags & TEXF_ALPHA)
6891         {
6892                 for (i = 0;i < width * height;i++)
6893                 {
6894                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6895                         {
6896                                 skinframe->hasalpha = true;
6897                                 break;
6898                         }
6899                 }
6900                 if (r_loadfog && skinframe->hasalpha)
6901                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6902         }
6903
6904         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6905         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6906
6907         return skinframe;
6908 }
6909
6910 skinframe_t *R_SkinFrame_LoadMissing(void)
6911 {
6912         skinframe_t *skinframe;
6913
6914         if (cls.state == ca_dedicated)
6915                 return NULL;
6916
6917         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6918         skinframe->stain = NULL;
6919         skinframe->merged = NULL;
6920         skinframe->base = NULL;
6921         skinframe->pants = NULL;
6922         skinframe->shirt = NULL;
6923         skinframe->nmap = NULL;
6924         skinframe->gloss = NULL;
6925         skinframe->glow = NULL;
6926         skinframe->fog = NULL;
6927         skinframe->reflect = NULL;
6928         skinframe->hasalpha = false;
6929
6930         skinframe->avgcolor[0] = rand() / RAND_MAX;
6931         skinframe->avgcolor[1] = rand() / RAND_MAX;
6932         skinframe->avgcolor[2] = rand() / RAND_MAX;
6933         skinframe->avgcolor[3] = 1;
6934
6935         return skinframe;
6936 }
6937
6938 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6939 typedef struct suffixinfo_s
6940 {
6941         const char *suffix;
6942         qboolean flipx, flipy, flipdiagonal;
6943 }
6944 suffixinfo_t;
6945 static suffixinfo_t suffix[3][6] =
6946 {
6947         {
6948                 {"px",   false, false, false},
6949                 {"nx",   false, false, false},
6950                 {"py",   false, false, false},
6951                 {"ny",   false, false, false},
6952                 {"pz",   false, false, false},
6953                 {"nz",   false, false, false}
6954         },
6955         {
6956                 {"posx", false, false, false},
6957                 {"negx", false, false, false},
6958                 {"posy", false, false, false},
6959                 {"negy", false, false, false},
6960                 {"posz", false, false, false},
6961                 {"negz", false, false, false}
6962         },
6963         {
6964                 {"rt",    true, false,  true},
6965                 {"lf",   false,  true,  true},
6966                 {"ft",    true,  true, false},
6967                 {"bk",   false, false, false},
6968                 {"up",    true, false,  true},
6969                 {"dn",    true, false,  true}
6970         }
6971 };
6972
6973 static int componentorder[4] = {0, 1, 2, 3};
6974
6975 rtexture_t *R_LoadCubemap(const char *basename)
6976 {
6977         int i, j, cubemapsize;
6978         unsigned char *cubemappixels, *image_buffer;
6979         rtexture_t *cubemaptexture;
6980         char name[256];
6981         // must start 0 so the first loadimagepixels has no requested width/height
6982         cubemapsize = 0;
6983         cubemappixels = NULL;
6984         cubemaptexture = NULL;
6985         // keep trying different suffix groups (posx, px, rt) until one loads
6986         for (j = 0;j < 3 && !cubemappixels;j++)
6987         {
6988                 // load the 6 images in the suffix group
6989                 for (i = 0;i < 6;i++)
6990                 {
6991                         // generate an image name based on the base and and suffix
6992                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6993                         // load it
6994                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6995                         {
6996                                 // an image loaded, make sure width and height are equal
6997                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6998                                 {
6999                                         // if this is the first image to load successfully, allocate the cubemap memory
7000                                         if (!cubemappixels && image_width >= 1)
7001                                         {
7002                                                 cubemapsize = image_width;
7003                                                 // note this clears to black, so unavailable sides are black
7004                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7005                                         }
7006                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7007                                         if (cubemappixels)
7008                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
7009                                 }
7010                                 else
7011                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7012                                 // free the image
7013                                 Mem_Free(image_buffer);
7014                         }
7015                 }
7016         }
7017         // if a cubemap loaded, upload it
7018         if (cubemappixels)
7019         {
7020                 if (developer_loading.integer)
7021                         Con_Printf("loading cubemap \"%s\"\n", basename);
7022
7023                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7024                 Mem_Free(cubemappixels);
7025         }
7026         else
7027         {
7028                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7029                 if (developer_loading.integer)
7030                 {
7031                         Con_Printf("(tried tried images ");
7032                         for (j = 0;j < 3;j++)
7033                                 for (i = 0;i < 6;i++)
7034                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7035                         Con_Print(" and was unable to find any of them).\n");
7036                 }
7037         }
7038         return cubemaptexture;
7039 }
7040
7041 rtexture_t *R_GetCubemap(const char *basename)
7042 {
7043         int i;
7044         for (i = 0;i < r_texture_numcubemaps;i++)
7045                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7046                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7047         if (i >= MAX_CUBEMAPS)
7048                 return r_texture_whitecube;
7049         r_texture_numcubemaps++;
7050         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7051         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7052         return r_texture_cubemaps[i].texture;
7053 }
7054
7055 void R_FreeCubemaps(void)
7056 {
7057         int i;
7058         for (i = 0;i < r_texture_numcubemaps;i++)
7059         {
7060                 if (developer_loading.integer)
7061                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7062                 if (r_texture_cubemaps[i].texture)
7063                         R_FreeTexture(r_texture_cubemaps[i].texture);
7064         }
7065         r_texture_numcubemaps = 0;
7066 }
7067
7068 void R_Main_FreeViewCache(void)
7069 {
7070         if (r_refdef.viewcache.entityvisible)
7071                 Mem_Free(r_refdef.viewcache.entityvisible);
7072         if (r_refdef.viewcache.world_pvsbits)
7073                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7074         if (r_refdef.viewcache.world_leafvisible)
7075                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7076         if (r_refdef.viewcache.world_surfacevisible)
7077                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7078         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7079 }
7080
7081 void R_Main_ResizeViewCache(void)
7082 {
7083         int numentities = r_refdef.scene.numentities;
7084         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7085         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7086         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7087         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7088         if (r_refdef.viewcache.maxentities < numentities)
7089         {
7090                 r_refdef.viewcache.maxentities = numentities;
7091                 if (r_refdef.viewcache.entityvisible)
7092                         Mem_Free(r_refdef.viewcache.entityvisible);
7093                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7094         }
7095         if (r_refdef.viewcache.world_numclusters != numclusters)
7096         {
7097                 r_refdef.viewcache.world_numclusters = numclusters;
7098                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7099                 if (r_refdef.viewcache.world_pvsbits)
7100                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7101                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7102         }
7103         if (r_refdef.viewcache.world_numleafs != numleafs)
7104         {
7105                 r_refdef.viewcache.world_numleafs = numleafs;
7106                 if (r_refdef.viewcache.world_leafvisible)
7107                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7108                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7109         }
7110         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7111         {
7112                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7113                 if (r_refdef.viewcache.world_surfacevisible)
7114                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7115                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7116         }
7117 }
7118
7119 extern rtexture_t *loadingscreentexture;
7120 void gl_main_start(void)
7121 {
7122         loadingscreentexture = NULL;
7123         r_texture_blanknormalmap = NULL;
7124         r_texture_white = NULL;
7125         r_texture_grey128 = NULL;
7126         r_texture_black = NULL;
7127         r_texture_whitecube = NULL;
7128         r_texture_normalizationcube = NULL;
7129         r_texture_fogattenuation = NULL;
7130         r_texture_fogheighttexture = NULL;
7131         r_texture_gammaramps = NULL;
7132         r_texture_numcubemaps = 0;
7133
7134         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7135         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7136
7137         switch(vid.renderpath)
7138         {
7139         case RENDERPATH_GL20:
7140         case RENDERPATH_CGGL:
7141         case RENDERPATH_D3D9:
7142         case RENDERPATH_D3D10:
7143         case RENDERPATH_D3D11:
7144                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7145                 Cvar_SetValueQuick(&gl_combine, 1);
7146                 Cvar_SetValueQuick(&r_glsl, 1);
7147                 r_loadnormalmap = true;
7148                 r_loadgloss = true;
7149                 r_loadfog = false;
7150                 break;
7151         case RENDERPATH_GL13:
7152                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7153                 Cvar_SetValueQuick(&gl_combine, 1);
7154                 Cvar_SetValueQuick(&r_glsl, 0);
7155                 r_loadnormalmap = false;
7156                 r_loadgloss = false;
7157                 r_loadfog = true;
7158                 break;
7159         case RENDERPATH_GL11:
7160                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7161                 Cvar_SetValueQuick(&gl_combine, 0);
7162                 Cvar_SetValueQuick(&r_glsl, 0);
7163                 r_loadnormalmap = false;
7164                 r_loadgloss = false;
7165                 r_loadfog = true;
7166                 break;
7167         }
7168
7169         R_AnimCache_Free();
7170         R_FrameData_Reset();
7171
7172         r_numqueries = 0;
7173         r_maxqueries = 0;
7174         memset(r_queries, 0, sizeof(r_queries));
7175
7176         r_qwskincache = NULL;
7177         r_qwskincache_size = 0;
7178
7179         // set up r_skinframe loading system for textures
7180         memset(&r_skinframe, 0, sizeof(r_skinframe));
7181         r_skinframe.loadsequence = 1;
7182         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7183
7184         r_main_texturepool = R_AllocTexturePool();
7185         R_BuildBlankTextures();
7186         R_BuildNoTexture();
7187         if (vid.support.arb_texture_cube_map)
7188         {
7189                 R_BuildWhiteCube();
7190                 R_BuildNormalizationCube();
7191         }
7192         r_texture_fogattenuation = NULL;
7193         r_texture_fogheighttexture = NULL;
7194         r_texture_gammaramps = NULL;
7195         //r_texture_fogintensity = NULL;
7196         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7197         memset(&r_waterstate, 0, sizeof(r_waterstate));
7198         r_glsl_permutation = NULL;
7199         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7200         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7201         glslshaderstring = NULL;
7202 #ifdef SUPPORTCG
7203         r_cg_permutation = NULL;
7204         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7205         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7206         cgshaderstring = NULL;
7207 #endif
7208 #ifdef SUPPORTD3D
7209         r_hlsl_permutation = NULL;
7210         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7211         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7212         hlslshaderstring = NULL;
7213 #endif
7214         memset(&r_svbsp, 0, sizeof (r_svbsp));
7215
7216         r_refdef.fogmasktable_density = 0;
7217 }
7218
7219 void gl_main_shutdown(void)
7220 {
7221         R_AnimCache_Free();
7222         R_FrameData_Reset();
7223
7224         R_Main_FreeViewCache();
7225
7226         switch(vid.renderpath)
7227         {
7228         case RENDERPATH_GL11:
7229         case RENDERPATH_GL13:
7230         case RENDERPATH_GL20:
7231         case RENDERPATH_CGGL:
7232                 if (r_maxqueries)
7233                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7234                 break;
7235         case RENDERPATH_D3D9:
7236                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7237                 break;
7238         case RENDERPATH_D3D10:
7239                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7240                 break;
7241         case RENDERPATH_D3D11:
7242                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7243                 break;
7244         }
7245
7246         r_numqueries = 0;
7247         r_maxqueries = 0;
7248         memset(r_queries, 0, sizeof(r_queries));
7249
7250         r_qwskincache = NULL;
7251         r_qwskincache_size = 0;
7252
7253         // clear out the r_skinframe state
7254         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7255         memset(&r_skinframe, 0, sizeof(r_skinframe));
7256
7257         if (r_svbsp.nodes)
7258                 Mem_Free(r_svbsp.nodes);
7259         memset(&r_svbsp, 0, sizeof (r_svbsp));
7260         R_FreeTexturePool(&r_main_texturepool);
7261         loadingscreentexture = NULL;
7262         r_texture_blanknormalmap = NULL;
7263         r_texture_white = NULL;
7264         r_texture_grey128 = NULL;
7265         r_texture_black = NULL;
7266         r_texture_whitecube = NULL;
7267         r_texture_normalizationcube = NULL;
7268         r_texture_fogattenuation = NULL;
7269         r_texture_fogheighttexture = NULL;
7270         r_texture_gammaramps = NULL;
7271         r_texture_numcubemaps = 0;
7272         //r_texture_fogintensity = NULL;
7273         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7274         memset(&r_waterstate, 0, sizeof(r_waterstate));
7275         R_GLSL_Restart_f();
7276 }
7277
7278 extern void CL_ParseEntityLump(char *entitystring);
7279 void gl_main_newmap(void)
7280 {
7281         // FIXME: move this code to client
7282         char *entities, entname[MAX_QPATH];
7283         if (r_qwskincache)
7284                 Mem_Free(r_qwskincache);
7285         r_qwskincache = NULL;
7286         r_qwskincache_size = 0;
7287         if (cl.worldmodel)
7288         {
7289                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7290                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7291                 {
7292                         CL_ParseEntityLump(entities);
7293                         Mem_Free(entities);
7294                         return;
7295                 }
7296                 if (cl.worldmodel->brush.entities)
7297                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7298         }
7299         R_Main_FreeViewCache();
7300
7301         R_FrameData_Reset();
7302 }
7303
7304 void GL_Main_Init(void)
7305 {
7306         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7307
7308         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7309         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7310         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7311         if (gamemode == GAME_NEHAHRA)
7312         {
7313                 Cvar_RegisterVariable (&gl_fogenable);
7314                 Cvar_RegisterVariable (&gl_fogdensity);
7315                 Cvar_RegisterVariable (&gl_fogred);
7316                 Cvar_RegisterVariable (&gl_foggreen);
7317                 Cvar_RegisterVariable (&gl_fogblue);
7318                 Cvar_RegisterVariable (&gl_fogstart);
7319                 Cvar_RegisterVariable (&gl_fogend);
7320                 Cvar_RegisterVariable (&gl_skyclip);
7321         }
7322         Cvar_RegisterVariable(&r_motionblur);
7323         Cvar_RegisterVariable(&r_motionblur_maxblur);
7324         Cvar_RegisterVariable(&r_motionblur_bmin);
7325         Cvar_RegisterVariable(&r_motionblur_vmin);
7326         Cvar_RegisterVariable(&r_motionblur_vmax);
7327         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7328         Cvar_RegisterVariable(&r_motionblur_randomize);
7329         Cvar_RegisterVariable(&r_damageblur);
7330         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7331         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7332         Cvar_RegisterVariable(&r_equalize_entities_by);
7333         Cvar_RegisterVariable(&r_equalize_entities_to);
7334         Cvar_RegisterVariable(&r_depthfirst);
7335         Cvar_RegisterVariable(&r_useinfinitefarclip);
7336         Cvar_RegisterVariable(&r_farclip_base);
7337         Cvar_RegisterVariable(&r_farclip_world);
7338         Cvar_RegisterVariable(&r_nearclip);
7339         Cvar_RegisterVariable(&r_showbboxes);
7340         Cvar_RegisterVariable(&r_showsurfaces);
7341         Cvar_RegisterVariable(&r_showtris);
7342         Cvar_RegisterVariable(&r_shownormals);
7343         Cvar_RegisterVariable(&r_showlighting);
7344         Cvar_RegisterVariable(&r_showshadowvolumes);
7345         Cvar_RegisterVariable(&r_showcollisionbrushes);
7346         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7347         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7348         Cvar_RegisterVariable(&r_showdisabledepthtest);
7349         Cvar_RegisterVariable(&r_drawportals);
7350         Cvar_RegisterVariable(&r_drawentities);
7351         Cvar_RegisterVariable(&r_draw2d);
7352         Cvar_RegisterVariable(&r_drawworld);
7353         Cvar_RegisterVariable(&r_cullentities_trace);
7354         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7355         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7356         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7357         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7358         Cvar_RegisterVariable(&r_drawviewmodel);
7359         Cvar_RegisterVariable(&r_drawexteriormodel);
7360         Cvar_RegisterVariable(&r_speeds);
7361         Cvar_RegisterVariable(&r_fullbrights);
7362         Cvar_RegisterVariable(&r_wateralpha);
7363         Cvar_RegisterVariable(&r_dynamic);
7364         Cvar_RegisterVariable(&r_fakelight);
7365         Cvar_RegisterVariable(&r_fakelight_intensity);
7366         Cvar_RegisterVariable(&r_fullbright);
7367         Cvar_RegisterVariable(&r_shadows);
7368         Cvar_RegisterVariable(&r_shadows_darken);
7369         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7370         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7371         Cvar_RegisterVariable(&r_shadows_throwdistance);
7372         Cvar_RegisterVariable(&r_shadows_throwdirection);
7373         Cvar_RegisterVariable(&r_shadows_focus);
7374         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7375         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7376         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7377         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7378         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7379         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7380         Cvar_RegisterVariable(&r_fog_exp2);
7381         Cvar_RegisterVariable(&r_drawfog);
7382         Cvar_RegisterVariable(&r_transparentdepthmasking);
7383         Cvar_RegisterVariable(&r_texture_dds_load);
7384         Cvar_RegisterVariable(&r_texture_dds_save);
7385         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7386         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7387         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7388         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7389         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7390         Cvar_RegisterVariable(&r_textureunits);
7391         Cvar_RegisterVariable(&gl_combine);
7392         Cvar_RegisterVariable(&r_glsl);
7393         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7394         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7395         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7396         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7397         Cvar_RegisterVariable(&r_glsl_postprocess);
7398         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7399         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7400         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7401         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7402         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7403         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7404         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7405         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7406
7407         Cvar_RegisterVariable(&r_water);
7408         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7409         Cvar_RegisterVariable(&r_water_clippingplanebias);
7410         Cvar_RegisterVariable(&r_water_refractdistort);
7411         Cvar_RegisterVariable(&r_water_reflectdistort);
7412         Cvar_RegisterVariable(&r_water_scissormode);
7413         Cvar_RegisterVariable(&r_lerpsprites);
7414         Cvar_RegisterVariable(&r_lerpmodels);
7415         Cvar_RegisterVariable(&r_lerplightstyles);
7416         Cvar_RegisterVariable(&r_waterscroll);
7417         Cvar_RegisterVariable(&r_bloom);
7418         Cvar_RegisterVariable(&r_bloom_colorscale);
7419         Cvar_RegisterVariable(&r_bloom_brighten);
7420         Cvar_RegisterVariable(&r_bloom_blur);
7421         Cvar_RegisterVariable(&r_bloom_resolution);
7422         Cvar_RegisterVariable(&r_bloom_colorexponent);
7423         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7424         Cvar_RegisterVariable(&r_hdr);
7425         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7426         Cvar_RegisterVariable(&r_hdr_glowintensity);
7427         Cvar_RegisterVariable(&r_hdr_range);
7428         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7429         Cvar_RegisterVariable(&developer_texturelogging);
7430         Cvar_RegisterVariable(&gl_lightmaps);
7431         Cvar_RegisterVariable(&r_test);
7432         Cvar_RegisterVariable(&r_glsl_saturation);
7433         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7434         Cvar_RegisterVariable(&r_framedatasize);
7435         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7436                 Cvar_SetValue("r_fullbrights", 0);
7437         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7438
7439         Cvar_RegisterVariable(&r_track_sprites);
7440         Cvar_RegisterVariable(&r_track_sprites_flags);
7441         Cvar_RegisterVariable(&r_track_sprites_scalew);
7442         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7443         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7444         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7445 }
7446
7447 extern void R_Textures_Init(void);
7448 extern void GL_Draw_Init(void);
7449 extern void GL_Main_Init(void);
7450 extern void R_Shadow_Init(void);
7451 extern void R_Sky_Init(void);
7452 extern void GL_Surf_Init(void);
7453 extern void R_Particles_Init(void);
7454 extern void R_Explosion_Init(void);
7455 extern void gl_backend_init(void);
7456 extern void Sbar_Init(void);
7457 extern void R_LightningBeams_Init(void);
7458 extern void Mod_RenderInit(void);
7459 extern void Font_Init(void);
7460
7461 void Render_Init(void)
7462 {
7463         gl_backend_init();
7464         R_Textures_Init();
7465         GL_Main_Init();
7466         Font_Init();
7467         GL_Draw_Init();
7468         R_Shadow_Init();
7469         R_Sky_Init();
7470         GL_Surf_Init();
7471         Sbar_Init();
7472         R_Particles_Init();
7473         R_Explosion_Init();
7474         R_LightningBeams_Init();
7475         Mod_RenderInit();
7476 }
7477
7478 /*
7479 ===============
7480 GL_Init
7481 ===============
7482 */
7483 extern char *ENGINE_EXTENSIONS;
7484 void GL_Init (void)
7485 {
7486         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7487         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7488         gl_version = (const char *)qglGetString(GL_VERSION);
7489         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7490
7491         if (!gl_extensions)
7492                 gl_extensions = "";
7493         if (!gl_platformextensions)
7494                 gl_platformextensions = "";
7495
7496         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7497         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7498         Con_Printf("GL_VERSION: %s\n", gl_version);
7499         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7500         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7501
7502         VID_CheckExtensions();
7503
7504         // LordHavoc: report supported extensions
7505         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7506
7507         // clear to black (loading plaque will be seen over this)
7508         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7509 }
7510
7511 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7512 {
7513         int i;
7514         mplane_t *p;
7515         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7516         {
7517                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7518                 if (i == 4)
7519                         continue;
7520                 p = r_refdef.view.frustum + i;
7521                 switch(p->signbits)
7522                 {
7523                 default:
7524                 case 0:
7525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7526                                 return true;
7527                         break;
7528                 case 1:
7529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7530                                 return true;
7531                         break;
7532                 case 2:
7533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7534                                 return true;
7535                         break;
7536                 case 3:
7537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7538                                 return true;
7539                         break;
7540                 case 4:
7541                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7542                                 return true;
7543                         break;
7544                 case 5:
7545                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 6:
7549                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 case 7:
7553                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7554                                 return true;
7555                         break;
7556                 }
7557         }
7558         return false;
7559 }
7560
7561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7562 {
7563         int i;
7564         const mplane_t *p;
7565         for (i = 0;i < numplanes;i++)
7566         {
7567                 p = planes + i;
7568                 switch(p->signbits)
7569                 {
7570                 default:
7571                 case 0:
7572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7573                                 return true;
7574                         break;
7575                 case 1:
7576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7577                                 return true;
7578                         break;
7579                 case 2:
7580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7581                                 return true;
7582                         break;
7583                 case 3:
7584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7585                                 return true;
7586                         break;
7587                 case 4:
7588                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7589                                 return true;
7590                         break;
7591                 case 5:
7592                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7593                                 return true;
7594                         break;
7595                 case 6:
7596                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7597                                 return true;
7598                         break;
7599                 case 7:
7600                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7601                                 return true;
7602                         break;
7603                 }
7604         }
7605         return false;
7606 }
7607
7608 //==================================================================================
7609
7610 // LordHavoc: this stores temporary data used within the same frame
7611
7612 qboolean r_framedata_failed;
7613 static size_t r_framedata_size;
7614 static size_t r_framedata_current;
7615 static void *r_framedata_base;
7616
7617 void R_FrameData_Reset(void)
7618 {
7619         if (r_framedata_base)
7620                 Mem_Free(r_framedata_base);
7621         r_framedata_base = NULL;
7622         r_framedata_size = 0;
7623         r_framedata_current = 0;
7624         r_framedata_failed = false;
7625 }
7626
7627 void R_FrameData_NewFrame(void)
7628 {
7629         size_t wantedsize;
7630         if (r_framedata_failed)
7631                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7632         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7633         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7634         if (r_framedata_size != wantedsize)
7635         {
7636                 r_framedata_size = wantedsize;
7637                 if (r_framedata_base)
7638                         Mem_Free(r_framedata_base);
7639                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7640         }
7641         r_framedata_current = 0;
7642         r_framedata_failed = false;
7643 }
7644
7645 void *R_FrameData_Alloc(size_t size)
7646 {
7647         void *data;
7648
7649         // align to 16 byte boundary
7650         size = (size + 15) & ~15;
7651         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7652         r_framedata_current += size;
7653
7654         // check overflow
7655         if (r_framedata_current > r_framedata_size)
7656                 r_framedata_failed = true;
7657
7658         // return NULL on everything after a failure
7659         if (r_framedata_failed)
7660                 return NULL;
7661
7662         return data;
7663 }
7664
7665 void *R_FrameData_Store(size_t size, void *data)
7666 {
7667         void *d = R_FrameData_Alloc(size);
7668         if (d)
7669                 memcpy(d, data, size);
7670         return d;
7671 }
7672
7673 //==================================================================================
7674
7675 // LordHavoc: animcache originally written by Echon, rewritten since then
7676
7677 /**
7678  * Animation cache prevents re-generating mesh data for an animated model
7679  * multiple times in one frame for lighting, shadowing, reflections, etc.
7680  */
7681
7682 void R_AnimCache_Free(void)
7683 {
7684 }
7685
7686 void R_AnimCache_ClearCache(void)
7687 {
7688         int i;
7689         entity_render_t *ent;
7690
7691         for (i = 0;i < r_refdef.scene.numentities;i++)
7692         {
7693                 ent = r_refdef.scene.entities[i];
7694                 ent->animcache_vertex3f = NULL;
7695                 ent->animcache_normal3f = NULL;
7696                 ent->animcache_svector3f = NULL;
7697                 ent->animcache_tvector3f = NULL;
7698                 ent->animcache_vertexposition = NULL;
7699                 ent->animcache_vertexmesh = NULL;
7700                 ent->animcache_vertexpositionbuffer = NULL;
7701                 ent->animcache_vertexmeshbuffer = NULL;
7702         }
7703 }
7704
7705 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7706 {
7707         int i;
7708
7709         // identical memory layout, so no need to allocate...
7710         // this also provides the vertexposition structure to everything, e.g.
7711         // depth masked rendering currently uses it even if having separate
7712         // arrays
7713         // NOTE: get rid of this optimization if changing it to e.g. 4f
7714         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7715
7716         // TODO:
7717         // get rid of following uses of VERTEXPOSITION, change to the array:
7718         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7719         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7720         // R_DrawTextureSurfaceList_DepthOnly
7721         // R_Q1BSP_DrawShadowMap
7722
7723         switch(vid.renderpath)
7724         {
7725         case RENDERPATH_GL20:
7726         case RENDERPATH_CGGL:
7727                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7728                 if (gl_mesh_separatearrays.integer)
7729                         return;
7730                 break;
7731         case RENDERPATH_D3D9:
7732         case RENDERPATH_D3D10:
7733         case RENDERPATH_D3D11:
7734                 // always need the meshbuffers
7735                 break;
7736         case RENDERPATH_GL13:
7737         case RENDERPATH_GL11:
7738                 // never need the meshbuffers
7739                 return;
7740         }
7741
7742         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7743                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7744         /*
7745         if (!ent->animcache_vertexposition)
7746                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7747         */
7748         if (ent->animcache_vertexposition)
7749         {
7750                 /*
7751                 for (i = 0;i < numvertices;i++)
7752                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7753                 */
7754                 // TODO: upload vertex buffer?
7755         }
7756         if (ent->animcache_vertexmesh)
7757         {
7758                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7759                 for (i = 0;i < numvertices;i++)
7760                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7761                 if (ent->animcache_svector3f)
7762                         for (i = 0;i < numvertices;i++)
7763                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7764                 if (ent->animcache_tvector3f)
7765                         for (i = 0;i < numvertices;i++)
7766                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7767                 if (ent->animcache_normal3f)
7768                         for (i = 0;i < numvertices;i++)
7769                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7770                 // TODO: upload vertex buffer?
7771         }
7772 }
7773
7774 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7775 {
7776         dp_model_t *model = ent->model;
7777         int numvertices;
7778         // see if it's already cached this frame
7779         if (ent->animcache_vertex3f)
7780         {
7781                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7782                 if (wantnormals || wanttangents)
7783                 {
7784                         if (ent->animcache_normal3f)
7785                                 wantnormals = false;
7786                         if (ent->animcache_svector3f)
7787                                 wanttangents = false;
7788                         if (wantnormals || wanttangents)
7789                         {
7790                                 numvertices = model->surfmesh.num_vertices;
7791                                 if (wantnormals)
7792                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7793                                 if (wanttangents)
7794                                 {
7795                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7796                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7797                                 }
7798                                 if (!r_framedata_failed)
7799                                 {
7800                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7801                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7802                                 }
7803                         }
7804                 }
7805         }
7806         else
7807         {
7808                 // see if this ent is worth caching
7809                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7810                         return false;
7811                 // get some memory for this entity and generate mesh data
7812                 numvertices = model->surfmesh.num_vertices;
7813                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814                 if (wantnormals)
7815                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7816                 if (wanttangents)
7817                 {
7818                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7819                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7820                 }
7821                 if (!r_framedata_failed)
7822                 {
7823                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7824                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7825                 }
7826         }
7827         return !r_framedata_failed;
7828 }
7829
7830 void R_AnimCache_CacheVisibleEntities(void)
7831 {
7832         int i;
7833         qboolean wantnormals = true;
7834         qboolean wanttangents = !r_showsurfaces.integer;
7835
7836         switch(vid.renderpath)
7837         {
7838         case RENDERPATH_GL20:
7839         case RENDERPATH_CGGL:
7840         case RENDERPATH_D3D9:
7841         case RENDERPATH_D3D10:
7842         case RENDERPATH_D3D11:
7843                 break;
7844         case RENDERPATH_GL13:
7845         case RENDERPATH_GL11:
7846                 wanttangents = false;
7847                 break;
7848         }
7849
7850         if (r_shownormals.integer)
7851                 wanttangents = wantnormals = true;
7852
7853         // TODO: thread this
7854         // NOTE: R_PrepareRTLights() also caches entities
7855
7856         for (i = 0;i < r_refdef.scene.numentities;i++)
7857                 if (r_refdef.viewcache.entityvisible[i])
7858                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7859 }
7860
7861 //==================================================================================
7862
7863 static void R_View_UpdateEntityLighting (void)
7864 {
7865         int i;
7866         entity_render_t *ent;
7867         vec3_t tempdiffusenormal, avg;
7868         vec_t f, fa, fd, fdd;
7869         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7870
7871         for (i = 0;i < r_refdef.scene.numentities;i++)
7872         {
7873                 ent = r_refdef.scene.entities[i];
7874
7875                 // skip unseen models
7876                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7877                         continue;
7878
7879                 // skip bsp models
7880                 if (ent->model && ent->model->brush.num_leafs)
7881                 {
7882                         // TODO: use modellight for r_ambient settings on world?
7883                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7884                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7885                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7886                         continue;
7887                 }
7888
7889                 // fetch the lighting from the worldmodel data
7890                 VectorClear(ent->modellight_ambient);
7891                 VectorClear(ent->modellight_diffuse);
7892                 VectorClear(tempdiffusenormal);
7893                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7894                 {
7895                         vec3_t org;
7896                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7897
7898                         // complete lightning for lit sprites
7899                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7900                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7901                         {
7902                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7903                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7904                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7905                         }
7906                         else
7907                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7908
7909                         if(ent->flags & RENDER_EQUALIZE)
7910                         {
7911                                 // first fix up ambient lighting...
7912                                 if(r_equalize_entities_minambient.value > 0)
7913                                 {
7914                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7915                                         if(fd > 0)
7916                                         {
7917                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7918                                                 if(fa < r_equalize_entities_minambient.value * fd)
7919                                                 {
7920                                                         // solve:
7921                                                         //   fa'/fd' = minambient
7922                                                         //   fa'+0.25*fd' = fa+0.25*fd
7923                                                         //   ...
7924                                                         //   fa' = fd' * minambient
7925                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7926                                                         //   ...
7927                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7928                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7929                                                         //   ...
7930                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7931                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
7932                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7933                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7934                                                 }
7935                                         }
7936                                 }
7937
7938                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7939                                 {
7940                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7941                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7942                                         if(f > 0)
7943                                         {
7944                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7945                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7946                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7947                                         }
7948                                 }
7949                         }
7950                 }
7951                 else // highly rare
7952                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7953
7954                 // move the light direction into modelspace coordinates for lighting code
7955                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7956                 if(VectorLength2(ent->modellight_lightdir) == 0)
7957                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7958                 VectorNormalize(ent->modellight_lightdir);
7959         }
7960 }
7961
7962 #define MAX_LINEOFSIGHTTRACES 64
7963
7964 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7965 {
7966         int i;
7967         vec3_t boxmins, boxmaxs;
7968         vec3_t start;
7969         vec3_t end;
7970         dp_model_t *model = r_refdef.scene.worldmodel;
7971
7972         if (!model || !model->brush.TraceLineOfSight)
7973                 return true;
7974
7975         // expand the box a little
7976         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7977         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7978         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7979         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7980         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7981         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7982
7983         // return true if eye is inside enlarged box
7984         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7985                 return true;
7986
7987         // try center
7988         VectorCopy(eye, start);
7989         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7990         if (model->brush.TraceLineOfSight(model, start, end))
7991                 return true;
7992
7993         // try various random positions
7994         for (i = 0;i < numsamples;i++)
7995         {
7996                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7997                 if (model->brush.TraceLineOfSight(model, start, end))
7998                         return true;
7999         }
8000
8001         return false;
8002 }
8003
8004
8005 static void R_View_UpdateEntityVisible (void)
8006 {
8007         int i;
8008         int renderimask;
8009         int samples;
8010         entity_render_t *ent;
8011
8012         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8013                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8014                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8015                 :                                                          RENDER_EXTERIORMODEL;
8016         if (!r_drawviewmodel.integer)
8017                 renderimask |= RENDER_VIEWMODEL;
8018         if (!r_drawexteriormodel.integer)
8019                 renderimask |= RENDER_EXTERIORMODEL;
8020         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8021         {
8022                 // worldmodel can check visibility
8023                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8024                 for (i = 0;i < r_refdef.scene.numentities;i++)
8025                 {
8026                         ent = r_refdef.scene.entities[i];
8027                         if (!(ent->flags & renderimask))
8028                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8029                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
8030                                 r_refdef.viewcache.entityvisible[i] = true;
8031                 }
8032                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8033                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8034                 {
8035                         for (i = 0;i < r_refdef.scene.numentities;i++)
8036                         {
8037                                 ent = r_refdef.scene.entities[i];
8038                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8039                                 {
8040                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8041                                         if (samples < 0)
8042                                                 continue; // temp entities do pvs only
8043                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8044                                                 ent->last_trace_visibility = realtime;
8045                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8046                                                 r_refdef.viewcache.entityvisible[i] = 0;
8047                                 }
8048                         }
8049                 }
8050         }
8051         else
8052         {
8053                 // no worldmodel or it can't check visibility
8054                 for (i = 0;i < r_refdef.scene.numentities;i++)
8055                 {
8056                         ent = r_refdef.scene.entities[i];
8057                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
8058                 }
8059         }
8060 }
8061
8062 /// only used if skyrendermasked, and normally returns false
8063 int R_DrawBrushModelsSky (void)
8064 {
8065         int i, sky;
8066         entity_render_t *ent;
8067
8068         sky = false;
8069         for (i = 0;i < r_refdef.scene.numentities;i++)
8070         {
8071                 if (!r_refdef.viewcache.entityvisible[i])
8072                         continue;
8073                 ent = r_refdef.scene.entities[i];
8074                 if (!ent->model || !ent->model->DrawSky)
8075                         continue;
8076                 ent->model->DrawSky(ent);
8077                 sky = true;
8078         }
8079         return sky;
8080 }
8081
8082 static void R_DrawNoModel(entity_render_t *ent);
8083 static void R_DrawModels(void)
8084 {
8085         int i;
8086         entity_render_t *ent;
8087
8088         for (i = 0;i < r_refdef.scene.numentities;i++)
8089         {
8090                 if (!r_refdef.viewcache.entityvisible[i])
8091                         continue;
8092                 ent = r_refdef.scene.entities[i];
8093                 r_refdef.stats.entities++;
8094                 if (ent->model && ent->model->Draw != NULL)
8095                         ent->model->Draw(ent);
8096                 else
8097                         R_DrawNoModel(ent);
8098         }
8099 }
8100
8101 static void R_DrawModelsDepth(void)
8102 {
8103         int i;
8104         entity_render_t *ent;
8105
8106         for (i = 0;i < r_refdef.scene.numentities;i++)
8107         {
8108                 if (!r_refdef.viewcache.entityvisible[i])
8109                         continue;
8110                 ent = r_refdef.scene.entities[i];
8111                 if (ent->model && ent->model->DrawDepth != NULL)
8112                         ent->model->DrawDepth(ent);
8113         }
8114 }
8115
8116 static void R_DrawModelsDebug(void)
8117 {
8118         int i;
8119         entity_render_t *ent;
8120
8121         for (i = 0;i < r_refdef.scene.numentities;i++)
8122         {
8123                 if (!r_refdef.viewcache.entityvisible[i])
8124                         continue;
8125                 ent = r_refdef.scene.entities[i];
8126                 if (ent->model && ent->model->DrawDebug != NULL)
8127                         ent->model->DrawDebug(ent);
8128         }
8129 }
8130
8131 static void R_DrawModelsAddWaterPlanes(void)
8132 {
8133         int i;
8134         entity_render_t *ent;
8135
8136         for (i = 0;i < r_refdef.scene.numentities;i++)
8137         {
8138                 if (!r_refdef.viewcache.entityvisible[i])
8139                         continue;
8140                 ent = r_refdef.scene.entities[i];
8141                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8142                         ent->model->DrawAddWaterPlanes(ent);
8143         }
8144 }
8145
8146 static void R_View_SetFrustum(const int *scissor)
8147 {
8148         int i;
8149         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8150         vec3_t forward, left, up, origin, v;
8151
8152         if(scissor)
8153         {
8154                 // flipped x coordinates (because x points left here)
8155                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8156                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8157
8158                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8159                 switch(vid.renderpath)
8160                 {
8161                         case RENDERPATH_D3D9:
8162                         case RENDERPATH_D3D10:
8163                         case RENDERPATH_D3D11:
8164                                 // non-flipped y coordinates
8165                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8166                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8167                                 break;
8168                         case RENDERPATH_GL11:
8169                         case RENDERPATH_GL13:
8170                         case RENDERPATH_GL20:
8171                         case RENDERPATH_CGGL:
8172                                 // non-flipped y coordinates
8173                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8174                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8175                                 break;
8176                 }
8177         }
8178
8179         // we can't trust r_refdef.view.forward and friends in reflected scenes
8180         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8181
8182 #if 0
8183         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8184         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8185         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8186         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8187         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8188         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8189         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8190         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8191         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8192         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8193         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8194         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8195 #endif
8196
8197 #if 0
8198         zNear = r_refdef.nearclip;
8199         nudge = 1.0 - 1.0 / (1<<23);
8200         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8201         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8202         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8203         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8204         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8205         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8206         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8207         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8208 #endif
8209
8210
8211
8212 #if 0
8213         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8214         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8215         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8216         r_refdef.view.frustum[0].dist = m[15] - m[12];
8217
8218         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8219         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8220         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8221         r_refdef.view.frustum[1].dist = m[15] + m[12];
8222
8223         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8224         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8225         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8226         r_refdef.view.frustum[2].dist = m[15] - m[13];
8227
8228         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8229         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8230         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8231         r_refdef.view.frustum[3].dist = m[15] + m[13];
8232
8233         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8234         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8235         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8236         r_refdef.view.frustum[4].dist = m[15] - m[14];
8237
8238         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8239         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8240         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8241         r_refdef.view.frustum[5].dist = m[15] + m[14];
8242 #endif
8243
8244         if (r_refdef.view.useperspective)
8245         {
8246                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8247                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8248                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8249                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8250                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8251
8252                 // then the normals from the corners relative to origin
8253                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8254                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8255                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8256                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8257
8258                 // in a NORMAL view, forward cross left == up
8259                 // in a REFLECTED view, forward cross left == down
8260                 // so our cross products above need to be adjusted for a left handed coordinate system
8261                 CrossProduct(forward, left, v);
8262                 if(DotProduct(v, up) < 0)
8263                 {
8264                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8265                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8266                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8267                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8268                 }
8269
8270                 // Leaving those out was a mistake, those were in the old code, and they
8271                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8272                 // I couldn't reproduce it after adding those normalizations. --blub
8273                 VectorNormalize(r_refdef.view.frustum[0].normal);
8274                 VectorNormalize(r_refdef.view.frustum[1].normal);
8275                 VectorNormalize(r_refdef.view.frustum[2].normal);
8276                 VectorNormalize(r_refdef.view.frustum[3].normal);
8277
8278                 // make the corners absolute
8279                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8280                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8281                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8282                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8283
8284                 // one more normal
8285                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8286
8287                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8288                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8289                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8290                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8291                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8292         }
8293         else
8294         {
8295                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8296                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8297                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8298                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8299                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8300                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8301                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8302                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8303                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8304                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8305         }
8306         r_refdef.view.numfrustumplanes = 5;
8307
8308         if (r_refdef.view.useclipplane)
8309         {
8310                 r_refdef.view.numfrustumplanes = 6;
8311                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8312         }
8313
8314         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8315                 PlaneClassify(r_refdef.view.frustum + i);
8316
8317         // LordHavoc: note to all quake engine coders, Quake had a special case
8318         // for 90 degrees which assumed a square view (wrong), so I removed it,
8319         // Quake2 has it disabled as well.
8320
8321         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8322         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8323         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8324         //PlaneClassify(&frustum[0]);
8325
8326         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8327         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8328         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8329         //PlaneClassify(&frustum[1]);
8330
8331         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8332         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8333         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8334         //PlaneClassify(&frustum[2]);
8335
8336         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8337         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8338         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8339         //PlaneClassify(&frustum[3]);
8340
8341         // nearclip plane
8342         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8343         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8344         //PlaneClassify(&frustum[4]);
8345 }
8346
8347 void R_View_UpdateWithScissor(const int *myscissor)
8348 {
8349         R_Main_ResizeViewCache();
8350         R_View_SetFrustum(myscissor);
8351         R_View_WorldVisibility(r_refdef.view.useclipplane);
8352         R_View_UpdateEntityVisible();
8353         R_View_UpdateEntityLighting();
8354 }
8355
8356 void R_View_Update(void)
8357 {
8358         R_Main_ResizeViewCache();
8359         R_View_SetFrustum(NULL);
8360         R_View_WorldVisibility(r_refdef.view.useclipplane);
8361         R_View_UpdateEntityVisible();
8362         R_View_UpdateEntityLighting();
8363 }
8364
8365 void R_SetupView(qboolean allowwaterclippingplane)
8366 {
8367         const float *customclipplane = NULL;
8368         float plane[4];
8369         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8370         {
8371                 // LordHavoc: couldn't figure out how to make this approach the
8372                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8373                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8374                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8375                         dist = r_refdef.view.clipplane.dist;
8376                 plane[0] = r_refdef.view.clipplane.normal[0];
8377                 plane[1] = r_refdef.view.clipplane.normal[1];
8378                 plane[2] = r_refdef.view.clipplane.normal[2];
8379                 plane[3] = dist;
8380                 customclipplane = plane;
8381         }
8382
8383         if (!r_refdef.view.useperspective)
8384                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
8385         else if (vid.stencil && r_useinfinitefarclip.integer)
8386                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
8387         else
8388                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
8389         R_SetViewport(&r_refdef.view.viewport);
8390 }
8391
8392 void R_EntityMatrix(const matrix4x4_t *matrix)
8393 {
8394         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8395         {
8396                 gl_modelmatrixchanged = false;
8397                 gl_modelmatrix = *matrix;
8398                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8399                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8400                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8401                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8402                 CHECKGLERROR
8403                 switch(vid.renderpath)
8404                 {
8405                 case RENDERPATH_D3D9:
8406 #ifdef SUPPORTD3D
8407                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8408                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8409 #endif
8410                         break;
8411                 case RENDERPATH_D3D10:
8412                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8413                         break;
8414                 case RENDERPATH_D3D11:
8415                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8416                         break;
8417                 case RENDERPATH_GL20:
8418                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8419                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8420                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8421                         break;
8422                 case RENDERPATH_CGGL:
8423 #ifdef SUPPORTCG
8424                         CHECKCGERROR
8425                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8426                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8427                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8428 #endif
8429                         break;
8430                 case RENDERPATH_GL13:
8431                 case RENDERPATH_GL11:
8432                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8433                         break;
8434                 }
8435         }
8436 }
8437
8438 void R_ResetViewRendering2D(void)
8439 {
8440         r_viewport_t viewport;
8441         DrawQ_Finish();
8442
8443         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8444         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
8445         R_SetViewport(&viewport);
8446         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8447         GL_Color(1, 1, 1, 1);
8448         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8449         GL_BlendFunc(GL_ONE, GL_ZERO);
8450         GL_AlphaTest(false);
8451         GL_ScissorTest(false);
8452         GL_DepthMask(false);
8453         GL_DepthRange(0, 1);
8454         GL_DepthTest(false);
8455         GL_DepthFunc(GL_LEQUAL);
8456         R_EntityMatrix(&identitymatrix);
8457         R_Mesh_ResetTextureState();
8458         GL_PolygonOffset(0, 0);
8459         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8460         switch(vid.renderpath)
8461         {
8462         case RENDERPATH_GL11:
8463         case RENDERPATH_GL13:
8464         case RENDERPATH_GL20:
8465         case RENDERPATH_CGGL:
8466                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8467                 break;
8468         case RENDERPATH_D3D9:
8469         case RENDERPATH_D3D10:
8470         case RENDERPATH_D3D11:
8471                 break;
8472         }
8473         GL_CullFace(GL_NONE);
8474 }
8475
8476 void R_ResetViewRendering3D(void)
8477 {
8478         DrawQ_Finish();
8479
8480         R_SetupView(true);
8481         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8482         GL_Color(1, 1, 1, 1);
8483         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8484         GL_BlendFunc(GL_ONE, GL_ZERO);
8485         GL_AlphaTest(false);
8486         GL_ScissorTest(true);
8487         GL_DepthMask(true);
8488         GL_DepthRange(0, 1);
8489         GL_DepthTest(true);
8490         GL_DepthFunc(GL_LEQUAL);
8491         R_EntityMatrix(&identitymatrix);
8492         R_Mesh_ResetTextureState();
8493         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8494         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8495         switch(vid.renderpath)
8496         {
8497         case RENDERPATH_GL11:
8498         case RENDERPATH_GL13:
8499         case RENDERPATH_GL20:
8500         case RENDERPATH_CGGL:
8501                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8502                 break;
8503         case RENDERPATH_D3D9:
8504         case RENDERPATH_D3D10:
8505         case RENDERPATH_D3D11:
8506                 break;
8507         }
8508         GL_CullFace(r_refdef.view.cullface_back);
8509 }
8510
8511 /*
8512 ================
8513 R_RenderView_UpdateViewVectors
8514 ================
8515 */
8516 static void R_RenderView_UpdateViewVectors(void)
8517 {
8518         // break apart the view matrix into vectors for various purposes
8519         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8520         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8521         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8522         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8523         // make an inverted copy of the view matrix for tracking sprites
8524         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8525 }
8526
8527 void R_RenderScene(void);
8528 void R_RenderWaterPlanes(void);
8529
8530 static void R_Water_StartFrame(void)
8531 {
8532         int i;
8533         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8534         r_waterstate_waterplane_t *p;
8535
8536         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8537                 return;
8538
8539         switch(vid.renderpath)
8540         {
8541         case RENDERPATH_GL20:
8542         case RENDERPATH_CGGL:
8543         case RENDERPATH_D3D9:
8544         case RENDERPATH_D3D10:
8545         case RENDERPATH_D3D11:
8546                 break;
8547         case RENDERPATH_GL13:
8548         case RENDERPATH_GL11:
8549                 return;
8550         }
8551
8552         // set waterwidth and waterheight to the water resolution that will be
8553         // used (often less than the screen resolution for faster rendering)
8554         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8555         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8556
8557         // calculate desired texture sizes
8558         // can't use water if the card does not support the texture size
8559         if (!r_water.integer || r_showsurfaces.integer)
8560                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8561         else if (vid.support.arb_texture_non_power_of_two)
8562         {
8563                 texturewidth = waterwidth;
8564                 textureheight = waterheight;
8565                 camerawidth = waterwidth;
8566                 cameraheight = waterheight;
8567         }
8568         else
8569         {
8570                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8571                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8572                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8573                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8574         }
8575
8576         // allocate textures as needed
8577         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8578         {
8579                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8580                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8581                 {
8582                         if (p->texture_refraction)
8583                                 R_FreeTexture(p->texture_refraction);
8584                         p->texture_refraction = NULL;
8585                         if (p->texture_reflection)
8586                                 R_FreeTexture(p->texture_reflection);
8587                         p->texture_reflection = NULL;
8588                         if (p->texture_camera)
8589                                 R_FreeTexture(p->texture_camera);
8590                         p->texture_camera = NULL;
8591                 }
8592                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8593                 r_waterstate.texturewidth = texturewidth;
8594                 r_waterstate.textureheight = textureheight;
8595                 r_waterstate.camerawidth = camerawidth;
8596                 r_waterstate.cameraheight = cameraheight;
8597         }
8598
8599         if (r_waterstate.texturewidth)
8600         {
8601                 r_waterstate.enabled = true;
8602
8603                 // when doing a reduced render (HDR) we want to use a smaller area
8604                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8605                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8606
8607                 // set up variables that will be used in shader setup
8608                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8609                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8610                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8611                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8612         }
8613
8614         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8615         r_waterstate.numwaterplanes = 0;
8616 }
8617
8618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8619 {
8620         int triangleindex, planeindex;
8621         const int *e;
8622         vec3_t vert[3];
8623         vec3_t normal;
8624         vec3_t center;
8625         mplane_t plane;
8626         r_waterstate_waterplane_t *p;
8627         texture_t *t = R_GetCurrentTexture(surface->texture);
8628
8629         // just use the first triangle with a valid normal for any decisions
8630         VectorClear(normal);
8631         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8632         {
8633                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8635                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8636                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8637                 if (VectorLength2(normal) >= 0.001)
8638                         break;
8639         }
8640
8641         VectorCopy(normal, plane.normal);
8642         VectorNormalize(plane.normal);
8643         plane.dist = DotProduct(vert[0], plane.normal);
8644         PlaneClassify(&plane);
8645         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8646         {
8647                 // skip backfaces (except if nocullface is set)
8648                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8649                         return;
8650                 VectorNegate(plane.normal, plane.normal);
8651                 plane.dist *= -1;
8652                 PlaneClassify(&plane);
8653         }
8654
8655
8656         // find a matching plane if there is one
8657         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8658                 if(p->camera_entity == t->camera_entity)
8659                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8660                                 break;
8661         if (planeindex >= r_waterstate.maxwaterplanes)
8662                 return; // nothing we can do, out of planes
8663
8664         // if this triangle does not fit any known plane rendered this frame, add one
8665         if (planeindex >= r_waterstate.numwaterplanes)
8666         {
8667                 // store the new plane
8668                 r_waterstate.numwaterplanes++;
8669                 p->plane = plane;
8670                 // clear materialflags and pvs
8671                 p->materialflags = 0;
8672                 p->pvsvalid = false;
8673                 p->camera_entity = t->camera_entity;
8674                 VectorCopy(surface->mins, p->mins);
8675                 VectorCopy(surface->maxs, p->maxs);
8676         }
8677         else
8678         {
8679                 // merge mins/maxs
8680                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8681                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8682                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8683                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8684                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8685                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8686         }
8687         // merge this surface's materialflags into the waterplane
8688         p->materialflags |= t->currentmaterialflags;
8689         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8690         {
8691                 // merge this surface's PVS into the waterplane
8692                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8694                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8695                 {
8696                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8697                         p->pvsvalid = true;
8698                 }
8699         }
8700 }
8701
8702 static void R_Water_ProcessPlanes(void)
8703 {
8704         int myscissor[4];
8705         r_refdef_view_t originalview;
8706         r_refdef_view_t myview;
8707         int planeindex;
8708         r_waterstate_waterplane_t *p;
8709         vec3_t visorigin;
8710
8711         originalview = r_refdef.view;
8712
8713         // make sure enough textures are allocated
8714         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8715         {
8716                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8717                 {
8718                         if (!p->texture_refraction)
8719                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8720                         if (!p->texture_refraction)
8721                                 goto error;
8722                 }
8723                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8724                 {
8725                         if (!p->texture_camera)
8726                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8727                         if (!p->texture_camera)
8728                                 goto error;
8729                 }
8730
8731                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8732                 {
8733                         if (!p->texture_reflection)
8734                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8735                         if (!p->texture_reflection)
8736                                 goto error;
8737                 }
8738         }
8739
8740         // render views
8741         r_refdef.view = originalview;
8742         r_refdef.view.showdebug = false;
8743         r_refdef.view.width = r_waterstate.waterwidth;
8744         r_refdef.view.height = r_waterstate.waterheight;
8745         r_refdef.view.useclipplane = true;
8746         myview = r_refdef.view;
8747         r_waterstate.renderingscene = true;
8748         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8749         {
8750                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8751                 {
8752                         r_refdef.view = myview;
8753                         if(r_water_scissormode.integer)
8754                         {
8755                                 R_SetupView(true);
8756                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8757                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8758                         }
8759
8760                         // render reflected scene and copy into texture
8761                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8762                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8763                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8764                         r_refdef.view.clipplane = p->plane;
8765
8766                         // reverse the cullface settings for this render
8767                         r_refdef.view.cullface_front = GL_FRONT;
8768                         r_refdef.view.cullface_back = GL_BACK;
8769                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8770                         {
8771                                 r_refdef.view.usecustompvs = true;
8772                                 if (p->pvsvalid)
8773                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8774                                 else
8775                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8776                         }
8777
8778                         R_ResetViewRendering3D();
8779                         R_ClearScreen(r_refdef.fogenabled);
8780                         if(r_water_scissormode.integer & 2)
8781                                 R_View_UpdateWithScissor(myscissor);
8782                         else
8783                                 R_View_Update();
8784                         if(r_water_scissormode.integer & 1)
8785                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8786                         R_RenderScene();
8787
8788                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8789                 }
8790
8791                 // render the normal view scene and copy into texture
8792                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
8793                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8794                 {
8795                         r_refdef.view = myview;
8796                         if(r_water_scissormode.integer)
8797                         {
8798                                 R_SetupView(true);
8799                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8800                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8801                         }
8802
8803                         r_waterstate.renderingrefraction = true;
8804
8805                         r_refdef.view.clipplane = p->plane;
8806                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8807                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8808
8809                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8810                         {
8811                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8812                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8813                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8814                                 R_RenderView_UpdateViewVectors();
8815                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8816                                 {
8817                                         r_refdef.view.usecustompvs = true;
8818                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8819                                 }
8820                         }
8821
8822                         PlaneClassify(&r_refdef.view.clipplane);
8823
8824                         R_ResetViewRendering3D();
8825                         R_ClearScreen(r_refdef.fogenabled);
8826                         if(r_water_scissormode.integer & 2)
8827                                 R_View_UpdateWithScissor(myscissor);
8828                         else
8829                                 R_View_Update();
8830                         if(r_water_scissormode.integer & 1)
8831                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8832                         R_RenderScene();
8833
8834                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8835                         r_waterstate.renderingrefraction = false;
8836                 }
8837                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8838                 {
8839                         r_refdef.view = myview;
8840
8841                         r_refdef.view.clipplane = p->plane;
8842                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8843                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8844
8845                         r_refdef.view.width = r_waterstate.camerawidth;
8846                         r_refdef.view.height = r_waterstate.cameraheight;
8847                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8848                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8849
8850                         if(p->camera_entity)
8851                         {
8852                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8853                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8854                         }
8855
8856                         // note: all of the view is used for displaying... so
8857                         // there is no use in scissoring
8858
8859                         // reverse the cullface settings for this render
8860                         r_refdef.view.cullface_front = GL_FRONT;
8861                         r_refdef.view.cullface_back = GL_BACK;
8862                         // also reverse the view matrix
8863                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8864                         R_RenderView_UpdateViewVectors();
8865                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8866                         {
8867                                 r_refdef.view.usecustompvs = true;
8868                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8869                         }
8870                         
8871                         // camera needs no clipplane
8872                         r_refdef.view.useclipplane = false;
8873
8874                         PlaneClassify(&r_refdef.view.clipplane);
8875
8876                         R_ResetViewRendering3D();
8877                         R_ClearScreen(r_refdef.fogenabled);
8878                         R_View_Update();
8879                         R_RenderScene();
8880
8881                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8882                         r_waterstate.renderingrefraction = false;
8883                 }
8884
8885         }
8886         r_waterstate.renderingscene = false;
8887         r_refdef.view = originalview;
8888         R_ResetViewRendering3D();
8889         R_ClearScreen(r_refdef.fogenabled);
8890         R_View_Update();
8891         return;
8892 error:
8893         r_refdef.view = originalview;
8894         r_waterstate.renderingscene = false;
8895         Cvar_SetValueQuick(&r_water, 0);
8896         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8897         return;
8898 }
8899
8900 void R_Bloom_StartFrame(void)
8901 {
8902         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8903
8904         switch(vid.renderpath)
8905         {
8906         case RENDERPATH_GL20:
8907         case RENDERPATH_CGGL:
8908         case RENDERPATH_D3D9:
8909         case RENDERPATH_D3D10:
8910         case RENDERPATH_D3D11:
8911                 break;
8912         case RENDERPATH_GL13:
8913         case RENDERPATH_GL11:
8914                 return;
8915         }
8916
8917         // set bloomwidth and bloomheight to the bloom resolution that will be
8918         // used (often less than the screen resolution for faster rendering)
8919         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8920         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8921         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8922         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8923         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8924
8925         // calculate desired texture sizes
8926         if (vid.support.arb_texture_non_power_of_two)
8927         {
8928                 screentexturewidth = r_refdef.view.width;
8929                 screentextureheight = r_refdef.view.height;
8930                 bloomtexturewidth = r_bloomstate.bloomwidth;
8931                 bloomtextureheight = r_bloomstate.bloomheight;
8932         }
8933         else
8934         {
8935                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8936                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8937                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8938                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8939         }
8940
8941         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
8942         {
8943                 Cvar_SetValueQuick(&r_hdr, 0);
8944                 Cvar_SetValueQuick(&r_bloom, 0);
8945                 Cvar_SetValueQuick(&r_motionblur, 0);
8946                 Cvar_SetValueQuick(&r_damageblur, 0);
8947         }
8948
8949         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
8950                 screentexturewidth = screentextureheight = 0;
8951         if (!r_hdr.integer && !r_bloom.integer)
8952                 bloomtexturewidth = bloomtextureheight = 0;
8953
8954         // allocate textures as needed
8955         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8956         {
8957                 if (r_bloomstate.texture_screen)
8958                         R_FreeTexture(r_bloomstate.texture_screen);
8959                 r_bloomstate.texture_screen = NULL;
8960                 r_bloomstate.screentexturewidth = screentexturewidth;
8961                 r_bloomstate.screentextureheight = screentextureheight;
8962                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8963                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8964         }
8965         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8966         {
8967                 if (r_bloomstate.texture_bloom)
8968                         R_FreeTexture(r_bloomstate.texture_bloom);
8969                 r_bloomstate.texture_bloom = NULL;
8970                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8971                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8972                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8973                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8974         }
8975
8976         // when doing a reduced render (HDR) we want to use a smaller area
8977         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8978         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8979         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8980         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8981         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8982
8983         // set up a texcoord array for the full resolution screen image
8984         // (we have to keep this around to copy back during final render)
8985         r_bloomstate.screentexcoord2f[0] = 0;
8986         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8987         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8988         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8989         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8990         r_bloomstate.screentexcoord2f[5] = 0;
8991         r_bloomstate.screentexcoord2f[6] = 0;
8992         r_bloomstate.screentexcoord2f[7] = 0;
8993
8994         // set up a texcoord array for the reduced resolution bloom image
8995         // (which will be additive blended over the screen image)
8996         r_bloomstate.bloomtexcoord2f[0] = 0;
8997         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8998         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8999         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9000         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9001         r_bloomstate.bloomtexcoord2f[5] = 0;
9002         r_bloomstate.bloomtexcoord2f[6] = 0;
9003         r_bloomstate.bloomtexcoord2f[7] = 0;
9004
9005         switch(vid.renderpath)
9006         {
9007         case RENDERPATH_GL11:
9008         case RENDERPATH_GL13:
9009         case RENDERPATH_GL20:
9010         case RENDERPATH_CGGL:
9011                 break;
9012         case RENDERPATH_D3D9:
9013         case RENDERPATH_D3D10:
9014         case RENDERPATH_D3D11:
9015                 {
9016                         int i;
9017                         for (i = 0;i < 4;i++)
9018                         {
9019                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9020                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9021                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9022                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9023                         }
9024                 }
9025                 break;
9026         }
9027
9028         if (r_hdr.integer || r_bloom.integer)
9029         {
9030                 r_bloomstate.enabled = true;
9031                 r_bloomstate.hdr = r_hdr.integer != 0;
9032         }
9033
9034         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
9035 }
9036
9037 void R_Bloom_CopyBloomTexture(float colorscale)
9038 {
9039         r_refdef.stats.bloom++;
9040
9041         // scale down screen texture to the bloom texture size
9042         CHECKGLERROR
9043         R_SetViewport(&r_bloomstate.viewport);
9044         GL_BlendFunc(GL_ONE, GL_ZERO);
9045         GL_Color(colorscale, colorscale, colorscale, 1);
9046         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9047         switch(vid.renderpath)
9048         {
9049         case RENDERPATH_GL11:
9050         case RENDERPATH_GL13:
9051         case RENDERPATH_GL20:
9052         case RENDERPATH_CGGL:
9053                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9054                 break;
9055         case RENDERPATH_D3D9:
9056         case RENDERPATH_D3D10:
9057         case RENDERPATH_D3D11:
9058                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9059                 break;
9060         }
9061         // TODO: do boxfilter scale-down in shader?
9062         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9063         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9064         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9065
9066         // we now have a bloom image in the framebuffer
9067         // copy it into the bloom image texture for later processing
9068         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9069         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9070 }
9071
9072 void R_Bloom_CopyHDRTexture(void)
9073 {
9074         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9075         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9076 }
9077
9078 void R_Bloom_MakeTexture(void)
9079 {
9080         int x, range, dir;
9081         float xoffset, yoffset, r, brighten;
9082
9083         r_refdef.stats.bloom++;
9084
9085         R_ResetViewRendering2D();
9086
9087         // we have a bloom image in the framebuffer
9088         CHECKGLERROR
9089         R_SetViewport(&r_bloomstate.viewport);
9090
9091         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9092         {
9093                 x *= 2;
9094                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9095                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9096                 GL_Color(r,r,r,1);
9097                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9098                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9099                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9100                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9101
9102                 // copy the vertically blurred bloom view to a texture
9103                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9104                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9105         }
9106
9107         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9108         brighten = r_bloom_brighten.value;
9109         if (r_hdr.integer)
9110                 brighten *= r_hdr_range.value;
9111         brighten = sqrt(brighten);
9112         if(range >= 1)
9113                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9114         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9115
9116         for (dir = 0;dir < 2;dir++)
9117         {
9118                 // blend on at multiple vertical offsets to achieve a vertical blur
9119                 // TODO: do offset blends using GLSL
9120                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9121                 GL_BlendFunc(GL_ONE, GL_ZERO);
9122                 for (x = -range;x <= range;x++)
9123                 {
9124                         if (!dir){xoffset = 0;yoffset = x;}
9125                         else {xoffset = x;yoffset = 0;}
9126                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9127                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9128                         // compute a texcoord array with the specified x and y offset
9129                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9130                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9131                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9132                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9133                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9134                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9135                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9136                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9137                         // this r value looks like a 'dot' particle, fading sharply to
9138                         // black at the edges
9139                         // (probably not realistic but looks good enough)
9140                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9141                         //r = brighten/(range*2+1);
9142                         r = brighten / (range * 2 + 1);
9143                         if(range >= 1)
9144                                 r *= (1 - x*x/(float)(range*range));
9145                         GL_Color(r, r, r, 1);
9146                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9147                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9148                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9149                         GL_BlendFunc(GL_ONE, GL_ONE);
9150                 }
9151
9152                 // copy the vertically blurred bloom view to a texture
9153                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9154                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9155         }
9156 }
9157
9158 void R_HDR_RenderBloomTexture(void)
9159 {
9160         int oldwidth, oldheight;
9161         float oldcolorscale;
9162
9163         oldcolorscale = r_refdef.view.colorscale;
9164         oldwidth = r_refdef.view.width;
9165         oldheight = r_refdef.view.height;
9166         r_refdef.view.width = r_bloomstate.bloomwidth;
9167         r_refdef.view.height = r_bloomstate.bloomheight;
9168
9169         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9170         // TODO: add exposure compensation features
9171         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9172
9173         r_refdef.view.showdebug = false;
9174         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9175
9176         R_ResetViewRendering3D();
9177
9178         R_ClearScreen(r_refdef.fogenabled);
9179         if (r_timereport_active)
9180                 R_TimeReport("HDRclear");
9181
9182         R_View_Update();
9183         if (r_timereport_active)
9184                 R_TimeReport("visibility");
9185
9186         // only do secondary renders with HDR if r_hdr is 2 or higher
9187         r_waterstate.numwaterplanes = 0;
9188         if (r_waterstate.enabled && r_hdr.integer >= 2)
9189                 R_RenderWaterPlanes();
9190
9191         r_refdef.view.showdebug = true;
9192         R_RenderScene();
9193         r_waterstate.numwaterplanes = 0;
9194
9195         R_ResetViewRendering2D();
9196
9197         R_Bloom_CopyHDRTexture();
9198         R_Bloom_MakeTexture();
9199
9200         // restore the view settings
9201         r_refdef.view.width = oldwidth;
9202         r_refdef.view.height = oldheight;
9203         r_refdef.view.colorscale = oldcolorscale;
9204
9205         R_ResetViewRendering3D();
9206
9207         R_ClearScreen(r_refdef.fogenabled);
9208         if (r_timereport_active)
9209                 R_TimeReport("viewclear");
9210 }
9211
9212 static void R_BlendView(void)
9213 {
9214         unsigned int permutation;
9215         float uservecs[4][4];
9216
9217         switch (vid.renderpath)
9218         {
9219         case RENDERPATH_GL20:
9220         case RENDERPATH_CGGL:
9221         case RENDERPATH_D3D9:
9222         case RENDERPATH_D3D10:
9223         case RENDERPATH_D3D11:
9224                 permutation =
9225                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9226                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9227                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9228                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9229                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9230
9231                 if (r_bloomstate.texture_screen)
9232                 {
9233                         // make sure the buffer is available
9234                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9235
9236                         R_ResetViewRendering2D();
9237
9238                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9239                         {
9240                                 // declare variables
9241                                 float speed;
9242                                 static float avgspeed;
9243
9244                                 speed = VectorLength(cl.movement_velocity);
9245
9246                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9247                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9248
9249                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9250                                 speed = bound(0, speed, 1);
9251                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9252
9253                                 // calculate values into a standard alpha
9254                                 cl.motionbluralpha = 1 - exp(-
9255                                                 (
9256                                                  (r_motionblur.value * speed / 80)
9257                                                  +
9258                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9259                                                 )
9260                                                 /
9261                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9262                                            );
9263
9264                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9265                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9266                                 // apply the blur
9267                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9268                                 {
9269                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9270                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9271                                         switch(vid.renderpath)
9272                                         {
9273                                         case RENDERPATH_GL11:
9274                                         case RENDERPATH_GL13:
9275                                         case RENDERPATH_GL20:
9276                                         case RENDERPATH_CGGL:
9277                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9278                                                 break;
9279                                         case RENDERPATH_D3D9:
9280                                         case RENDERPATH_D3D10:
9281                                         case RENDERPATH_D3D11:
9282                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9283                                                 break;
9284                                         }
9285                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9286                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9287                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9288                                 }
9289                         }
9290
9291                         // copy view into the screen texture
9292                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9293                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9294                 }
9295                 else if (!r_bloomstate.texture_bloom)
9296                 {
9297                         // we may still have to do view tint...
9298                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9299                         {
9300                                 // apply a color tint to the whole view
9301                                 R_ResetViewRendering2D();
9302                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9303                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9304                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9305                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9306                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9307                         }
9308                         break; // no screen processing, no bloom, skip it
9309                 }
9310
9311                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9312                 {
9313                         // render simple bloom effect
9314                         // copy the screen and shrink it and darken it for the bloom process
9315                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9316                         // make the bloom texture
9317                         R_Bloom_MakeTexture();
9318                 }
9319
9320 #if _MSC_VER >= 1400
9321 #define sscanf sscanf_s
9322 #endif
9323                 memset(uservecs, 0, sizeof(uservecs));
9324                 if (r_glsl_postprocess_uservec1_enable.integer)
9325                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9326                 if (r_glsl_postprocess_uservec2_enable.integer)
9327                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9328                 if (r_glsl_postprocess_uservec3_enable.integer)
9329                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9330                 if (r_glsl_postprocess_uservec4_enable.integer)
9331                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9332
9333                 R_ResetViewRendering2D();
9334                 GL_Color(1, 1, 1, 1);
9335                 GL_BlendFunc(GL_ONE, GL_ZERO);
9336
9337                 switch(vid.renderpath)
9338                 {
9339                 case RENDERPATH_GL20:
9340                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9341                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9342                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9343                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9344                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9345                         if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9346                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9347                         if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9348                         if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9349                         if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9350                         if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9351                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9352                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9353                         if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9354                         break;
9355                 case RENDERPATH_CGGL:
9356 #ifdef SUPPORTCG
9357                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9359                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9360                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9361                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9362                         if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
9363                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9364                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
9365                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
9366                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
9367                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
9368                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9369                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9370                         if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9371 #endif
9372                         break;
9373                 case RENDERPATH_D3D9:
9374 #ifdef SUPPORTD3D
9375                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9376                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9377                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9378                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9379                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9380                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9381                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9382                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9383                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9384                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9385                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9386                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9387                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9388                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9389                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9390 #endif
9391                         break;
9392                 case RENDERPATH_D3D10:
9393                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9394                         break;
9395                 case RENDERPATH_D3D11:
9396                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9397                         break;
9398                 default:
9399                         break;
9400                 }
9401                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9402                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9403                 break;
9404         case RENDERPATH_GL13:
9405         case RENDERPATH_GL11:
9406                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9407                 {
9408                         // apply a color tint to the whole view
9409                         R_ResetViewRendering2D();
9410                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9411                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9412                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9413                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9414                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9415                 }
9416                 break;
9417         }
9418 }
9419
9420 matrix4x4_t r_waterscrollmatrix;
9421
9422 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9423 {
9424         if (r_refdef.fog_density)
9425         {
9426                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9427                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9428                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9429
9430                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9431                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9432                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9433                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9434
9435                 {
9436                         vec3_t fogvec;
9437                         VectorCopy(r_refdef.fogcolor, fogvec);
9438                         //   color.rgb *= ContrastBoost * SceneBrightness;
9439                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9440                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9441                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9442                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9443                 }
9444         }
9445 }
9446
9447 void R_UpdateVariables(void)
9448 {
9449         R_Textures_Frame();
9450
9451         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9452
9453         r_refdef.farclip = r_farclip_base.value;
9454         if (r_refdef.scene.worldmodel)
9455                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9456         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9457
9458         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9459                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9460         r_refdef.polygonfactor = 0;
9461         r_refdef.polygonoffset = 0;
9462         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9463         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9464
9465         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9466         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9467         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9468         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9469         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9470         if (FAKELIGHT_ENABLED)
9471         {
9472                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9473         }
9474         if (r_showsurfaces.integer)
9475         {
9476                 r_refdef.scene.rtworld = false;
9477                 r_refdef.scene.rtworldshadows = false;
9478                 r_refdef.scene.rtdlight = false;
9479                 r_refdef.scene.rtdlightshadows = false;
9480                 r_refdef.lightmapintensity = 0;
9481         }
9482
9483         if (gamemode == GAME_NEHAHRA)
9484         {
9485                 if (gl_fogenable.integer)
9486                 {
9487                         r_refdef.oldgl_fogenable = true;
9488                         r_refdef.fog_density = gl_fogdensity.value;
9489                         r_refdef.fog_red = gl_fogred.value;
9490                         r_refdef.fog_green = gl_foggreen.value;
9491                         r_refdef.fog_blue = gl_fogblue.value;
9492                         r_refdef.fog_alpha = 1;
9493                         r_refdef.fog_start = 0;
9494                         r_refdef.fog_end = gl_skyclip.value;
9495                         r_refdef.fog_height = 1<<30;
9496                         r_refdef.fog_fadedepth = 128;
9497                 }
9498                 else if (r_refdef.oldgl_fogenable)
9499                 {
9500                         r_refdef.oldgl_fogenable = false;
9501                         r_refdef.fog_density = 0;
9502                         r_refdef.fog_red = 0;
9503                         r_refdef.fog_green = 0;
9504                         r_refdef.fog_blue = 0;
9505                         r_refdef.fog_alpha = 0;
9506                         r_refdef.fog_start = 0;
9507                         r_refdef.fog_end = 0;
9508                         r_refdef.fog_height = 1<<30;
9509                         r_refdef.fog_fadedepth = 128;
9510                 }
9511         }
9512
9513         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9514         r_refdef.fog_start = max(0, r_refdef.fog_start);
9515         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9516
9517         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9518
9519         if (r_refdef.fog_density && r_drawfog.integer)
9520         {
9521                 r_refdef.fogenabled = true;
9522                 // this is the point where the fog reaches 0.9986 alpha, which we
9523                 // consider a good enough cutoff point for the texture
9524                 // (0.9986 * 256 == 255.6)
9525                 if (r_fog_exp2.integer)
9526                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9527                 else
9528                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9529                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9530                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9531                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9532                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9533                         R_BuildFogHeightTexture();
9534                 // fog color was already set
9535                 // update the fog texture
9536                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
9537                         R_BuildFogTexture();
9538                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9539                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9540         }
9541         else
9542                 r_refdef.fogenabled = false;
9543
9544         switch(vid.renderpath)
9545         {
9546         case RENDERPATH_GL20:
9547         case RENDERPATH_CGGL:
9548         case RENDERPATH_D3D9:
9549         case RENDERPATH_D3D10:
9550         case RENDERPATH_D3D11:
9551                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9552                 {
9553                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9554                         {
9555                                 // build GLSL gamma texture
9556 #define RAMPWIDTH 256
9557                                 unsigned short ramp[RAMPWIDTH * 3];
9558                                 unsigned char rampbgr[RAMPWIDTH][4];
9559                                 int i;
9560
9561                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9562
9563                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9564                                 for(i = 0; i < RAMPWIDTH; ++i)
9565                                 {
9566                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9567                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9568                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9569                                         rampbgr[i][3] = 0;
9570                                 }
9571                                 if (r_texture_gammaramps)
9572                                 {
9573                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9574                                 }
9575                                 else
9576                                 {
9577                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9578                                 }
9579                         }
9580                 }
9581                 else
9582                 {
9583                         // remove GLSL gamma texture
9584                 }
9585                 break;
9586         case RENDERPATH_GL13:
9587         case RENDERPATH_GL11:
9588                 break;
9589         }
9590 }
9591
9592 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9593 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9594 /*
9595 ================
9596 R_SelectScene
9597 ================
9598 */
9599 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9600         if( scenetype != r_currentscenetype ) {
9601                 // store the old scenetype
9602                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9603                 r_currentscenetype = scenetype;
9604                 // move in the new scene
9605                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9606         }
9607 }
9608
9609 /*
9610 ================
9611 R_GetScenePointer
9612 ================
9613 */
9614 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9615 {
9616         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9617         if( scenetype == r_currentscenetype ) {
9618                 return &r_refdef.scene;
9619         } else {
9620                 return &r_scenes_store[ scenetype ];
9621         }
9622 }
9623
9624 /*
9625 ================
9626 R_RenderView
9627 ================
9628 */
9629 void R_RenderView(void)
9630 {
9631         if (r_timereport_active)
9632                 R_TimeReport("start");
9633         r_textureframe++; // used only by R_GetCurrentTexture
9634         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9635
9636         if(R_CompileShader_CheckStaticParms())
9637                 R_GLSL_Restart_f();
9638
9639         if (!r_drawentities.integer)
9640                 r_refdef.scene.numentities = 0;
9641
9642         R_AnimCache_ClearCache();
9643         R_FrameData_NewFrame();
9644
9645         if (r_refdef.view.isoverlay)
9646         {
9647                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9648                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9649                 R_TimeReport("depthclear");
9650
9651                 r_refdef.view.showdebug = false;
9652
9653                 r_waterstate.enabled = false;
9654                 r_waterstate.numwaterplanes = 0;
9655
9656                 R_RenderScene();
9657
9658                 CHECKGLERROR
9659                 return;
9660         }
9661
9662         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9663                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9664
9665         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9666
9667         R_RenderView_UpdateViewVectors();
9668
9669         R_Shadow_UpdateWorldLightSelection();
9670
9671         R_Bloom_StartFrame();
9672         R_Water_StartFrame();
9673
9674         CHECKGLERROR
9675         if (r_timereport_active)
9676                 R_TimeReport("viewsetup");
9677
9678         R_ResetViewRendering3D();
9679
9680         if (r_refdef.view.clear || r_refdef.fogenabled)
9681         {
9682                 R_ClearScreen(r_refdef.fogenabled);
9683                 if (r_timereport_active)
9684                         R_TimeReport("viewclear");
9685         }
9686         r_refdef.view.clear = true;
9687
9688         // this produces a bloom texture to be used in R_BlendView() later
9689         if (r_hdr.integer && r_bloomstate.bloomwidth)
9690         {
9691                 R_HDR_RenderBloomTexture();
9692                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9693                 r_textureframe++; // used only by R_GetCurrentTexture
9694         }
9695
9696         r_refdef.view.showdebug = true;
9697
9698         R_View_Update();
9699         if (r_timereport_active)
9700                 R_TimeReport("visibility");
9701
9702         r_waterstate.numwaterplanes = 0;
9703         if (r_waterstate.enabled)
9704                 R_RenderWaterPlanes();
9705
9706         R_RenderScene();
9707         r_waterstate.numwaterplanes = 0;
9708
9709         R_BlendView();
9710         if (r_timereport_active)
9711                 R_TimeReport("blendview");
9712
9713         GL_Scissor(0, 0, vid.width, vid.height);
9714         GL_ScissorTest(false);
9715
9716         CHECKGLERROR
9717 }
9718
9719 void R_RenderWaterPlanes(void)
9720 {
9721         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9722         {
9723                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9724                 if (r_timereport_active)
9725                         R_TimeReport("waterworld");
9726         }
9727
9728         // don't let sound skip if going slow
9729         if (r_refdef.scene.extraupdate)
9730                 S_ExtraUpdate ();
9731
9732         R_DrawModelsAddWaterPlanes();
9733         if (r_timereport_active)
9734                 R_TimeReport("watermodels");
9735
9736         if (r_waterstate.numwaterplanes)
9737         {
9738                 R_Water_ProcessPlanes();
9739                 if (r_timereport_active)
9740                         R_TimeReport("waterscenes");
9741         }
9742 }
9743
9744 extern void R_DrawLightningBeams (void);
9745 extern void VM_CL_AddPolygonsToMeshQueue (void);
9746 extern void R_DrawPortals (void);
9747 extern cvar_t cl_locs_show;
9748 static void R_DrawLocs(void);
9749 static void R_DrawEntityBBoxes(void);
9750 static void R_DrawModelDecals(void);
9751 extern void R_DrawModelShadows(void);
9752 extern void R_DrawModelShadowMaps(void);
9753 extern cvar_t cl_decals_newsystem;
9754 extern qboolean r_shadow_usingdeferredprepass;
9755 void R_RenderScene(void)
9756 {
9757         qboolean shadowmapping = false;
9758
9759         if (r_timereport_active)
9760                 R_TimeReport("beginscene");
9761
9762         r_refdef.stats.renders++;
9763
9764         R_UpdateFogColor();
9765
9766         // don't let sound skip if going slow
9767         if (r_refdef.scene.extraupdate)
9768                 S_ExtraUpdate ();
9769
9770         R_MeshQueue_BeginScene();
9771
9772         R_SkyStartFrame();
9773
9774         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
9775
9776         if (r_timereport_active)
9777                 R_TimeReport("skystartframe");
9778
9779         if (cl.csqc_vidvars.drawworld)
9780         {
9781                 // don't let sound skip if going slow
9782                 if (r_refdef.scene.extraupdate)
9783                         S_ExtraUpdate ();
9784
9785                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9786                 {
9787                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9788                         if (r_timereport_active)
9789                                 R_TimeReport("worldsky");
9790                 }
9791
9792                 if (R_DrawBrushModelsSky() && r_timereport_active)
9793                         R_TimeReport("bmodelsky");
9794
9795                 if (skyrendermasked && skyrenderlater)
9796                 {
9797                         // we have to force off the water clipping plane while rendering sky
9798                         R_SetupView(false);
9799                         R_Sky();
9800                         R_SetupView(true);
9801                         if (r_timereport_active)
9802                                 R_TimeReport("sky");
9803                 }
9804         }
9805
9806         R_AnimCache_CacheVisibleEntities();
9807         if (r_timereport_active)
9808                 R_TimeReport("animation");
9809
9810         R_Shadow_PrepareLights();
9811         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9812                 R_Shadow_PrepareModelShadows();
9813         if (r_timereport_active)
9814                 R_TimeReport("preparelights");
9815
9816         if (R_Shadow_ShadowMappingEnabled())
9817                 shadowmapping = true;
9818
9819         if (r_shadow_usingdeferredprepass)
9820                 R_Shadow_DrawPrepass();
9821
9822         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9823         {
9824                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9825                 if (r_timereport_active)
9826                         R_TimeReport("worlddepth");
9827         }
9828         if (r_depthfirst.integer >= 2)
9829         {
9830                 R_DrawModelsDepth();
9831                 if (r_timereport_active)
9832                         R_TimeReport("modeldepth");
9833         }
9834
9835         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9836         {
9837                 R_DrawModelShadowMaps();
9838                 R_ResetViewRendering3D();
9839                 // don't let sound skip if going slow
9840                 if (r_refdef.scene.extraupdate)
9841                         S_ExtraUpdate ();
9842         }
9843
9844         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9845         {
9846                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9847                 if (r_timereport_active)
9848                         R_TimeReport("world");
9849         }
9850
9851         // don't let sound skip if going slow
9852         if (r_refdef.scene.extraupdate)
9853                 S_ExtraUpdate ();
9854
9855         R_DrawModels();
9856         if (r_timereport_active)
9857                 R_TimeReport("models");
9858
9859         // don't let sound skip if going slow
9860         if (r_refdef.scene.extraupdate)
9861                 S_ExtraUpdate ();
9862
9863         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9864         {
9865                 R_DrawModelShadows();
9866                 R_ResetViewRendering3D();
9867                 // don't let sound skip if going slow
9868                 if (r_refdef.scene.extraupdate)
9869                         S_ExtraUpdate ();
9870         }
9871
9872         if (!r_shadow_usingdeferredprepass)
9873         {
9874                 R_Shadow_DrawLights();
9875                 if (r_timereport_active)
9876                         R_TimeReport("rtlights");
9877         }
9878
9879         // don't let sound skip if going slow
9880         if (r_refdef.scene.extraupdate)
9881                 S_ExtraUpdate ();
9882
9883         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9884         {
9885                 R_DrawModelShadows();
9886                 R_ResetViewRendering3D();
9887                 // don't let sound skip if going slow
9888                 if (r_refdef.scene.extraupdate)
9889                         S_ExtraUpdate ();
9890         }
9891
9892         if (cl.csqc_vidvars.drawworld)
9893         {
9894                 if (cl_decals_newsystem.integer)
9895                 {
9896                         R_DrawModelDecals();
9897                         if (r_timereport_active)
9898                                 R_TimeReport("modeldecals");
9899                 }
9900                 else
9901                 {
9902                         R_DrawDecals();
9903                         if (r_timereport_active)
9904                                 R_TimeReport("decals");
9905                 }
9906
9907                 R_DrawParticles();
9908                 if (r_timereport_active)
9909                         R_TimeReport("particles");
9910
9911                 R_DrawExplosions();
9912                 if (r_timereport_active)
9913                         R_TimeReport("explosions");
9914
9915                 R_DrawLightningBeams();
9916                 if (r_timereport_active)
9917                         R_TimeReport("lightning");
9918         }
9919
9920         VM_CL_AddPolygonsToMeshQueue();
9921
9922         if (r_refdef.view.showdebug)
9923         {
9924                 if (cl_locs_show.integer)
9925                 {
9926                         R_DrawLocs();
9927                         if (r_timereport_active)
9928                                 R_TimeReport("showlocs");
9929                 }
9930
9931                 if (r_drawportals.integer)
9932                 {
9933                         R_DrawPortals();
9934                         if (r_timereport_active)
9935                                 R_TimeReport("portals");
9936                 }
9937
9938                 if (r_showbboxes.value > 0)
9939                 {
9940                         R_DrawEntityBBoxes();
9941                         if (r_timereport_active)
9942                                 R_TimeReport("bboxes");
9943                 }
9944         }
9945
9946         R_MeshQueue_RenderTransparent();
9947         if (r_timereport_active)
9948                 R_TimeReport("drawtrans");
9949
9950         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
9951         {
9952                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9953                 if (r_timereport_active)
9954                         R_TimeReport("worlddebug");
9955                 R_DrawModelsDebug();
9956                 if (r_timereport_active)
9957                         R_TimeReport("modeldebug");
9958         }
9959
9960         if (cl.csqc_vidvars.drawworld)
9961         {
9962                 R_Shadow_DrawCoronas();
9963                 if (r_timereport_active)
9964                         R_TimeReport("coronas");
9965         }
9966
9967 #if 0
9968         {
9969                 GL_DepthTest(false);
9970                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9971                 GL_Color(1, 1, 1, 1);
9972                 qglBegin(GL_POLYGON);
9973                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9974                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9975                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9976                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9977                 qglEnd();
9978                 qglBegin(GL_POLYGON);
9979                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9980                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9981                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9982                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9983                 qglEnd();
9984                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9985         }
9986 #endif
9987
9988         // don't let sound skip if going slow
9989         if (r_refdef.scene.extraupdate)
9990                 S_ExtraUpdate ();
9991
9992         R_ResetViewRendering2D();
9993 }
9994
9995 static const unsigned short bboxelements[36] =
9996 {
9997         5, 1, 3, 5, 3, 7,
9998         6, 2, 0, 6, 0, 4,
9999         7, 3, 2, 7, 2, 6,
10000         4, 0, 1, 4, 1, 5,
10001         4, 5, 7, 4, 7, 6,
10002         1, 0, 2, 1, 2, 3,
10003 };
10004
10005 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10006 {
10007         int i;
10008         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10009
10010         RSurf_ActiveWorldEntity();
10011
10012         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10013         GL_DepthMask(false);
10014         GL_DepthRange(0, 1);
10015         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10016 //      R_Mesh_ResetTextureState();
10017
10018         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10019         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10020         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10021         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10022         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10023         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10024         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10025         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10026         R_FillColors(color4f, 8, cr, cg, cb, ca);
10027         if (r_refdef.fogenabled)
10028         {
10029                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10030                 {
10031                         f1 = RSurf_FogVertex(v);
10032                         f2 = 1 - f1;
10033                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10034                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10035                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10036                 }
10037         }
10038         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10039         R_Mesh_ResetTextureState();
10040         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10041         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10042 }
10043
10044 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10045 {
10046         int i;
10047         float color[4];
10048         prvm_edict_t *edict;
10049         prvm_prog_t *prog_save = prog;
10050
10051         // this function draws bounding boxes of server entities
10052         if (!sv.active)
10053                 return;
10054
10055         GL_CullFace(GL_NONE);
10056         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10057
10058         prog = 0;
10059         SV_VM_Begin();
10060         for (i = 0;i < numsurfaces;i++)
10061         {
10062                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10063                 switch ((int)edict->fields.server->solid)
10064                 {
10065                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10066                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10067                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10068                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10069                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10070                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10071                 }
10072                 color[3] *= r_showbboxes.value;
10073                 color[3] = bound(0, color[3], 1);
10074                 GL_DepthTest(!r_showdisabledepthtest.integer);
10075                 GL_CullFace(r_refdef.view.cullface_front);
10076                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10077         }
10078         SV_VM_End();
10079         prog = prog_save;
10080 }
10081
10082 static void R_DrawEntityBBoxes(void)
10083 {
10084         int i;
10085         prvm_edict_t *edict;
10086         vec3_t center;
10087         prvm_prog_t *prog_save = prog;
10088
10089         // this function draws bounding boxes of server entities
10090         if (!sv.active)
10091                 return;
10092
10093         prog = 0;
10094         SV_VM_Begin();
10095         for (i = 0;i < prog->num_edicts;i++)
10096         {
10097                 edict = PRVM_EDICT_NUM(i);
10098                 if (edict->priv.server->free)
10099                         continue;
10100                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10101                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10102                         continue;
10103                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10104                         continue;
10105                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10106                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10107         }
10108         SV_VM_End();
10109         prog = prog_save;
10110 }
10111
10112 static const int nomodelelement3i[24] =
10113 {
10114         5, 2, 0,
10115         5, 1, 2,
10116         5, 0, 3,
10117         5, 3, 1,
10118         0, 2, 4,
10119         2, 1, 4,
10120         3, 0, 4,
10121         1, 3, 4
10122 };
10123
10124 static const unsigned short nomodelelement3s[24] =
10125 {
10126         5, 2, 0,
10127         5, 1, 2,
10128         5, 0, 3,
10129         5, 3, 1,
10130         0, 2, 4,
10131         2, 1, 4,
10132         3, 0, 4,
10133         1, 3, 4
10134 };
10135
10136 static const float nomodelvertex3f[6*3] =
10137 {
10138         -16,   0,   0,
10139          16,   0,   0,
10140           0, -16,   0,
10141           0,  16,   0,
10142           0,   0, -16,
10143           0,   0,  16
10144 };
10145
10146 static const float nomodelcolor4f[6*4] =
10147 {
10148         0.0f, 0.0f, 0.5f, 1.0f,
10149         0.0f, 0.0f, 0.5f, 1.0f,
10150         0.0f, 0.5f, 0.0f, 1.0f,
10151         0.0f, 0.5f, 0.0f, 1.0f,
10152         0.5f, 0.0f, 0.0f, 1.0f,
10153         0.5f, 0.0f, 0.0f, 1.0f
10154 };
10155
10156 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10157 {
10158         int i;
10159         float f1, f2, *c;
10160         float color4f[6*4];
10161
10162         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
10163
10164         // this is only called once per entity so numsurfaces is always 1, and
10165         // surfacelist is always {0}, so this code does not handle batches
10166
10167         if (rsurface.ent_flags & RENDER_ADDITIVE)
10168         {
10169                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10170                 GL_DepthMask(false);
10171         }
10172         else if (rsurface.colormod[3] < 1)
10173         {
10174                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10175                 GL_DepthMask(false);
10176         }
10177         else
10178         {
10179                 GL_BlendFunc(GL_ONE, GL_ZERO);
10180                 GL_DepthMask(true);
10181         }
10182         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10183         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10184         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10185         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10186         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10187         for (i = 0, c = color4f;i < 6;i++, c += 4)
10188         {
10189                 c[0] *= rsurface.colormod[0];
10190                 c[1] *= rsurface.colormod[1];
10191                 c[2] *= rsurface.colormod[2];
10192                 c[3] *= rsurface.colormod[3];
10193         }
10194         if (r_refdef.fogenabled)
10195         {
10196                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10197                 {
10198                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10199                         f2 = 1 - f1;
10200                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10201                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10202                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10203                 }
10204         }
10205 //      R_Mesh_ResetTextureState();
10206         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10207         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10208         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10209 }
10210
10211 void R_DrawNoModel(entity_render_t *ent)
10212 {
10213         vec3_t org;
10214         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10215         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10216                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10217         else
10218                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10219 }
10220
10221 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10222 {
10223         vec3_t right1, right2, diff, normal;
10224
10225         VectorSubtract (org2, org1, normal);
10226
10227         // calculate 'right' vector for start
10228         VectorSubtract (r_refdef.view.origin, org1, diff);
10229         CrossProduct (normal, diff, right1);
10230         VectorNormalize (right1);
10231
10232         // calculate 'right' vector for end
10233         VectorSubtract (r_refdef.view.origin, org2, diff);
10234         CrossProduct (normal, diff, right2);
10235         VectorNormalize (right2);
10236
10237         vert[ 0] = org1[0] + width * right1[0];
10238         vert[ 1] = org1[1] + width * right1[1];
10239         vert[ 2] = org1[2] + width * right1[2];
10240         vert[ 3] = org1[0] - width * right1[0];
10241         vert[ 4] = org1[1] - width * right1[1];
10242         vert[ 5] = org1[2] - width * right1[2];
10243         vert[ 6] = org2[0] - width * right2[0];
10244         vert[ 7] = org2[1] - width * right2[1];
10245         vert[ 8] = org2[2] - width * right2[2];
10246         vert[ 9] = org2[0] + width * right2[0];
10247         vert[10] = org2[1] + width * right2[1];
10248         vert[11] = org2[2] + width * right2[2];
10249 }
10250
10251 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
10252 {
10253         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10254         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10255         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10256         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10257         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10258         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10259         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10260         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10261         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10262         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10263         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10264         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10265 }
10266
10267 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10268 {
10269         int i;
10270         float *vertex3f;
10271         float v[3];
10272         VectorSet(v, x, y, z);
10273         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10274                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10275                         break;
10276         if (i == mesh->numvertices)
10277         {
10278                 if (mesh->numvertices < mesh->maxvertices)
10279                 {
10280                         VectorCopy(v, vertex3f);
10281                         mesh->numvertices++;
10282                 }
10283                 return mesh->numvertices;
10284         }
10285         else
10286                 return i;
10287 }
10288
10289 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10290 {
10291         int i;
10292         int *e, element[3];
10293         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10294         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10295         e = mesh->element3i + mesh->numtriangles * 3;
10296         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10297         {
10298                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10299                 if (mesh->numtriangles < mesh->maxtriangles)
10300                 {
10301                         *e++ = element[0];
10302                         *e++ = element[1];
10303                         *e++ = element[2];
10304                         mesh->numtriangles++;
10305                 }
10306                 element[1] = element[2];
10307         }
10308 }
10309
10310 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10311 {
10312         int i;
10313         int *e, element[3];
10314         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10315         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10316         e = mesh->element3i + mesh->numtriangles * 3;
10317         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10318         {
10319                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10320                 if (mesh->numtriangles < mesh->maxtriangles)
10321                 {
10322                         *e++ = element[0];
10323                         *e++ = element[1];
10324                         *e++ = element[2];
10325                         mesh->numtriangles++;
10326                 }
10327                 element[1] = element[2];
10328         }
10329 }
10330
10331 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10332 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10333 {
10334         int planenum, planenum2;
10335         int w;
10336         int tempnumpoints;
10337         mplane_t *plane, *plane2;
10338         double maxdist;
10339         double temppoints[2][256*3];
10340         // figure out how large a bounding box we need to properly compute this brush
10341         maxdist = 0;
10342         for (w = 0;w < numplanes;w++)
10343                 maxdist = max(maxdist, fabs(planes[w].dist));
10344         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10345         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10346         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10347         {
10348                 w = 0;
10349                 tempnumpoints = 4;
10350                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10351                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10352                 {
10353                         if (planenum2 == planenum)
10354                                 continue;
10355                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
10356                         w = !w;
10357                 }
10358                 if (tempnumpoints < 3)
10359                         continue;
10360                 // generate elements forming a triangle fan for this polygon
10361                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10362         }
10363 }
10364
10365 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
10366 {
10367         texturelayer_t *layer;
10368         layer = t->currentlayers + t->currentnumlayers++;
10369         layer->type = type;
10370         layer->depthmask = depthmask;
10371         layer->blendfunc1 = blendfunc1;
10372         layer->blendfunc2 = blendfunc2;
10373         layer->texture = texture;
10374         layer->texmatrix = *matrix;
10375         layer->color[0] = r;
10376         layer->color[1] = g;
10377         layer->color[2] = b;
10378         layer->color[3] = a;
10379 }
10380
10381 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10382 {
10383         if(parms[0] == 0 && parms[1] == 0)
10384                 return false;
10385         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10386                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10387                         return false;
10388         return true;
10389 }
10390
10391 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10392 {
10393         double index, f;
10394         index = parms[2] + r_refdef.scene.time * parms[3];
10395         index -= floor(index);
10396         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10397         {
10398         default:
10399         case Q3WAVEFUNC_NONE:
10400         case Q3WAVEFUNC_NOISE:
10401         case Q3WAVEFUNC_COUNT:
10402                 f = 0;
10403                 break;
10404         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10405         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10406         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10407         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10408         case Q3WAVEFUNC_TRIANGLE:
10409                 index *= 4;
10410                 f = index - floor(index);
10411                 if (index < 1)
10412                         f = f;
10413                 else if (index < 2)
10414                         f = 1 - f;
10415                 else if (index < 3)
10416                         f = -f;
10417                 else
10418                         f = -(1 - f);
10419                 break;
10420         }
10421         f = parms[0] + parms[1] * f;
10422         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10423                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10424         return (float) f;
10425 }
10426
10427 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10428 {
10429         int w, h, idx;
10430         float f;
10431         float tcmat[12];
10432         matrix4x4_t matrix, temp;
10433         switch(tcmod->tcmod)
10434         {
10435                 case Q3TCMOD_COUNT:
10436                 case Q3TCMOD_NONE:
10437                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10438                                 matrix = r_waterscrollmatrix;
10439                         else
10440                                 matrix = identitymatrix;
10441                         break;
10442                 case Q3TCMOD_ENTITYTRANSLATE:
10443                         // this is used in Q3 to allow the gamecode to control texcoord
10444                         // scrolling on the entity, which is not supported in darkplaces yet.
10445                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10446                         break;
10447                 case Q3TCMOD_ROTATE:
10448                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10449                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10450                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10451                         break;
10452                 case Q3TCMOD_SCALE:
10453                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10454                         break;
10455                 case Q3TCMOD_SCROLL:
10456                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10457                         break;
10458                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10459                         w = (int) tcmod->parms[0];
10460                         h = (int) tcmod->parms[1];
10461                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10462                         f = f - floor(f);
10463                         idx = (int) floor(f * w * h);
10464                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10465                         break;
10466                 case Q3TCMOD_STRETCH:
10467                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10468                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10469                         break;
10470                 case Q3TCMOD_TRANSFORM:
10471                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10472                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10473                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10474                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10475                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10476                         break;
10477                 case Q3TCMOD_TURBULENT:
10478                         // this is handled in the RSurf_PrepareVertices function
10479                         matrix = identitymatrix;
10480                         break;
10481         }
10482         temp = *texmatrix;
10483         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10484 }
10485
10486 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10487 {
10488         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10489         char name[MAX_QPATH];
10490         skinframe_t *skinframe;
10491         unsigned char pixels[296*194];
10492         strlcpy(cache->name, skinname, sizeof(cache->name));
10493         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10494         if (developer_loading.integer)
10495                 Con_Printf("loading %s\n", name);
10496         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10497         if (!skinframe || !skinframe->base)
10498         {
10499                 unsigned char *f;
10500                 fs_offset_t filesize;
10501                 skinframe = NULL;
10502                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10503                 if (f)
10504                 {
10505                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10506                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10507                         Mem_Free(f);
10508                 }
10509         }
10510         cache->skinframe = skinframe;
10511 }
10512
10513 texture_t *R_GetCurrentTexture(texture_t *t)
10514 {
10515         int i;
10516         const entity_render_t *ent = rsurface.entity;
10517         dp_model_t *model = ent->model;
10518         q3shaderinfo_layer_tcmod_t *tcmod;
10519
10520         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10521                 return t->currentframe;
10522         t->update_lastrenderframe = r_textureframe;
10523         t->update_lastrenderentity = (void *)ent;
10524
10525         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10526                 t->camera_entity = ent->entitynumber;
10527         else
10528                 t->camera_entity = 0;
10529
10530         // switch to an alternate material if this is a q1bsp animated material
10531         {
10532                 texture_t *texture = t;
10533                 int s = rsurface.ent_skinnum;
10534                 if ((unsigned int)s >= (unsigned int)model->numskins)
10535                         s = 0;
10536                 if (model->skinscenes)
10537                 {
10538                         if (model->skinscenes[s].framecount > 1)
10539                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10540                         else
10541                                 s = model->skinscenes[s].firstframe;
10542                 }
10543                 if (s > 0)
10544                         t = t + s * model->num_surfaces;
10545                 if (t->animated)
10546                 {
10547                         // use an alternate animation if the entity's frame is not 0,
10548                         // and only if the texture has an alternate animation
10549                         if (rsurface.ent_alttextures && t->anim_total[1])
10550                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10551                         else
10552                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10553                 }
10554                 texture->currentframe = t;
10555         }
10556
10557         // update currentskinframe to be a qw skin or animation frame
10558         if (rsurface.ent_qwskin >= 0)
10559         {
10560                 i = rsurface.ent_qwskin;
10561                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10562                 {
10563                         r_qwskincache_size = cl.maxclients;
10564                         if (r_qwskincache)
10565                                 Mem_Free(r_qwskincache);
10566                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10567                 }
10568                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10569                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10570                 t->currentskinframe = r_qwskincache[i].skinframe;
10571                 if (t->currentskinframe == NULL)
10572                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10573         }
10574         else if (t->numskinframes >= 2)
10575                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10576         if (t->backgroundnumskinframes >= 2)
10577                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10578
10579         t->currentmaterialflags = t->basematerialflags;
10580         t->currentalpha = rsurface.colormod[3];
10581         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10582                 t->currentalpha *= r_wateralpha.value;
10583         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10584                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10585         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10586                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10587         if (!(rsurface.ent_flags & RENDER_LIGHT))
10588                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10589         else if (FAKELIGHT_ENABLED)
10590         {
10591                         // no modellight if using fakelight for the map
10592         }
10593         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10594         {
10595                 // pick a model lighting mode
10596                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10597                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10598                 else
10599                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10600         }
10601         if (rsurface.ent_flags & RENDER_ADDITIVE)
10602                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10603         else if (t->currentalpha < 1)
10604                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10605         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10606                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10607         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10608                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10609         if (t->backgroundnumskinframes)
10610                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10611         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10612         {
10613                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10614                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10615         }
10616         else
10617                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10618         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10619                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10620
10621         // there is no tcmod
10622         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10623         {
10624                 t->currenttexmatrix = r_waterscrollmatrix;
10625                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10626         }
10627         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10628         {
10629                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10630                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10631         }
10632
10633         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10634                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10635         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10636                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10637
10638         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10639         if (t->currentskinframe->qpixels)
10640                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10641         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10642         if (!t->basetexture)
10643                 t->basetexture = r_texture_notexture;
10644         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10645         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10646         t->nmaptexture = t->currentskinframe->nmap;
10647         if (!t->nmaptexture)
10648                 t->nmaptexture = r_texture_blanknormalmap;
10649         t->glosstexture = r_texture_black;
10650         t->glowtexture = t->currentskinframe->glow;
10651         t->fogtexture = t->currentskinframe->fog;
10652         t->reflectmasktexture = t->currentskinframe->reflect;
10653         if (t->backgroundnumskinframes)
10654         {
10655                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10656                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10657                 t->backgroundglosstexture = r_texture_black;
10658                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10659                 if (!t->backgroundnmaptexture)
10660                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10661         }
10662         else
10663         {
10664                 t->backgroundbasetexture = r_texture_white;
10665                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10666                 t->backgroundglosstexture = r_texture_black;
10667                 t->backgroundglowtexture = NULL;
10668         }
10669         t->specularpower = r_shadow_glossexponent.value;
10670         // TODO: store reference values for these in the texture?
10671         t->specularscale = 0;
10672         if (r_shadow_gloss.integer > 0)
10673         {
10674                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10675                 {
10676                         if (r_shadow_glossintensity.value > 0)
10677                         {
10678                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10679                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10680                                 t->specularscale = r_shadow_glossintensity.value;
10681                         }
10682                 }
10683                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10684                 {
10685                         t->glosstexture = r_texture_white;
10686                         t->backgroundglosstexture = r_texture_white;
10687                         t->specularscale = r_shadow_gloss2intensity.value;
10688                         t->specularpower = r_shadow_gloss2exponent.value;
10689                 }
10690         }
10691         t->specularscale *= t->specularscalemod;
10692         t->specularpower *= t->specularpowermod;
10693
10694         // lightmaps mode looks bad with dlights using actual texturing, so turn
10695         // off the colormap and glossmap, but leave the normalmap on as it still
10696         // accurately represents the shading involved
10697         if (gl_lightmaps.integer)
10698         {
10699                 t->basetexture = r_texture_grey128;
10700                 t->pantstexture = r_texture_black;
10701                 t->shirttexture = r_texture_black;
10702                 t->nmaptexture = r_texture_blanknormalmap;
10703                 t->glosstexture = r_texture_black;
10704                 t->glowtexture = NULL;
10705                 t->fogtexture = NULL;
10706                 t->reflectmasktexture = NULL;
10707                 t->backgroundbasetexture = NULL;
10708                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10709                 t->backgroundglosstexture = r_texture_black;
10710                 t->backgroundglowtexture = NULL;
10711                 t->specularscale = 0;
10712                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10713         }
10714
10715         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10716         VectorClear(t->dlightcolor);
10717         t->currentnumlayers = 0;
10718         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10719         {
10720                 int blendfunc1, blendfunc2;
10721                 qboolean depthmask;
10722                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10723                 {
10724                         blendfunc1 = GL_SRC_ALPHA;
10725                         blendfunc2 = GL_ONE;
10726                 }
10727                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10728                 {
10729                         blendfunc1 = GL_SRC_ALPHA;
10730                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10731                 }
10732                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10733                 {
10734                         blendfunc1 = t->customblendfunc[0];
10735                         blendfunc2 = t->customblendfunc[1];
10736                 }
10737                 else
10738                 {
10739                         blendfunc1 = GL_ONE;
10740                         blendfunc2 = GL_ZERO;
10741                 }
10742                 // don't colormod evilblend textures
10743                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10744                         VectorSet(t->lightmapcolor, 1, 1, 1);
10745                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10746                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10747                 {
10748                         // fullbright is not affected by r_refdef.lightmapintensity
10749                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
10750                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10751                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
10752                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10753                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
10754                 }
10755                 else
10756                 {
10757                         vec3_t ambientcolor;
10758                         float colorscale;
10759                         // set the color tint used for lights affecting this surface
10760                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10761                         colorscale = 2;
10762                         // q3bsp has no lightmap updates, so the lightstylevalue that
10763                         // would normally be baked into the lightmap must be
10764                         // applied to the color
10765                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10766                         if (model->type == mod_brushq3)
10767                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10768                         colorscale *= r_refdef.lightmapintensity;
10769                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10770                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10771                         // basic lit geometry
10772                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
10773                         // add pants/shirt if needed
10774                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10775                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
10776                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10777                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
10778                         // now add ambient passes if needed
10779                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10780                         {
10781                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
10782                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10783                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
10784                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10785                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
10786                         }
10787                 }
10788                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10789                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
10790                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10791                 {
10792                         // if this is opaque use alpha blend which will darken the earlier
10793                         // passes cheaply.
10794                         //
10795                         // if this is an alpha blended material, all the earlier passes
10796                         // were darkened by fog already, so we only need to add the fog
10797                         // color ontop through the fog mask texture
10798                         //
10799                         // if this is an additive blended material, all the earlier passes
10800                         // were darkened by fog already, and we should not add fog color
10801                         // (because the background was not darkened, there is no fog color
10802                         // that was lost behind it).
10803                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
10804                 }
10805         }
10806
10807         return t->currentframe;
10808 }
10809
10810 rsurfacestate_t rsurface;
10811
10812 void R_Mesh_ResizeArrays(int newvertices)
10813 {
10814         unsigned char *base;
10815         size_t size;
10816         if (rsurface.array_size >= newvertices)
10817                 return;
10818         if (rsurface.array_base)
10819                 Mem_Free(rsurface.array_base);
10820         rsurface.array_size = (newvertices + 1023) & ~1023;
10821         size = 0;
10822         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10823         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10824         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10825         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10826         size += rsurface.array_size * sizeof(float[3]);
10827         size += rsurface.array_size * sizeof(float[3]);
10828         size += rsurface.array_size * sizeof(float[3]);
10829         size += rsurface.array_size * sizeof(float[3]);
10830         size += rsurface.array_size * sizeof(float[3]);
10831         size += rsurface.array_size * sizeof(float[3]);
10832         size += rsurface.array_size * sizeof(float[3]);
10833         size += rsurface.array_size * sizeof(float[3]);
10834         size += rsurface.array_size * sizeof(float[4]);
10835         size += rsurface.array_size * sizeof(float[2]);
10836         size += rsurface.array_size * sizeof(float[2]);
10837         size += rsurface.array_size * sizeof(float[4]);
10838         size += rsurface.array_size * sizeof(int[3]);
10839         size += rsurface.array_size * sizeof(unsigned short[3]);
10840         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10841         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10842         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10843         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10844         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10845         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10846         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10847         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10848         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10849         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10850         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10851         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10852         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10853         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10854         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10855         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10856         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10857         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10858         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10859 }
10860
10861 void RSurf_ActiveWorldEntity(void)
10862 {
10863         int newvertices;
10864         dp_model_t *model = r_refdef.scene.worldmodel;
10865         //if (rsurface.entity == r_refdef.scene.worldentity)
10866         //      return;
10867         rsurface.entity = r_refdef.scene.worldentity;
10868         rsurface.skeleton = NULL;
10869         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10870         rsurface.ent_skinnum = 0;
10871         rsurface.ent_qwskin = -1;
10872         rsurface.ent_shadertime = 0;
10873         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10874         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10875         if (rsurface.array_size < newvertices)
10876                 R_Mesh_ResizeArrays(newvertices);
10877         rsurface.matrix = identitymatrix;
10878         rsurface.inversematrix = identitymatrix;
10879         rsurface.matrixscale = 1;
10880         rsurface.inversematrixscale = 1;
10881         R_EntityMatrix(&identitymatrix);
10882         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10883         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10884         rsurface.fograngerecip = r_refdef.fograngerecip;
10885         rsurface.fogheightfade = r_refdef.fogheightfade;
10886         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10887         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10888         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10889         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10890         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10891         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10892         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10893         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10894         rsurface.colormod[3] = 1;
10895         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);
10896         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10897         rsurface.frameblend[0].lerp = 1;
10898         rsurface.ent_alttextures = false;
10899         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10900         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10901         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10902         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10903         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10904         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10905         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10906         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10907         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10908         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10909         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10910         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10911         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10912         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10913         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10914         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10915         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10916         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10917         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10918         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10919         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10920         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10921         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10922         rsurface.modelelement3i = model->surfmesh.data_element3i;
10923         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10924         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10925         rsurface.modelelement3s = model->surfmesh.data_element3s;
10926         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10927         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10928         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10929         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10930         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10931         rsurface.modelsurfaces = model->data_surfaces;
10932         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10933         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10934         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10935         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10936         rsurface.modelgeneratedvertex = false;
10937         rsurface.batchgeneratedvertex = false;
10938         rsurface.batchfirstvertex = 0;
10939         rsurface.batchnumvertices = 0;
10940         rsurface.batchfirsttriangle = 0;
10941         rsurface.batchnumtriangles = 0;
10942         rsurface.batchvertex3f  = NULL;
10943         rsurface.batchvertex3f_vertexbuffer = NULL;
10944         rsurface.batchvertex3f_bufferoffset = 0;
10945         rsurface.batchsvector3f = NULL;
10946         rsurface.batchsvector3f_vertexbuffer = NULL;
10947         rsurface.batchsvector3f_bufferoffset = 0;
10948         rsurface.batchtvector3f = NULL;
10949         rsurface.batchtvector3f_vertexbuffer = NULL;
10950         rsurface.batchtvector3f_bufferoffset = 0;
10951         rsurface.batchnormal3f  = NULL;
10952         rsurface.batchnormal3f_vertexbuffer = NULL;
10953         rsurface.batchnormal3f_bufferoffset = 0;
10954         rsurface.batchlightmapcolor4f = NULL;
10955         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10956         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10957         rsurface.batchtexcoordtexture2f = NULL;
10958         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10959         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10960         rsurface.batchtexcoordlightmap2f = NULL;
10961         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10962         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10963         rsurface.batchvertexmesh = NULL;
10964         rsurface.batchvertexmeshbuffer = NULL;
10965         rsurface.batchvertexposition = NULL;
10966         rsurface.batchvertexpositionbuffer = NULL;
10967         rsurface.batchelement3i = NULL;
10968         rsurface.batchelement3i_indexbuffer = NULL;
10969         rsurface.batchelement3i_bufferoffset = 0;
10970         rsurface.batchelement3s = NULL;
10971         rsurface.batchelement3s_indexbuffer = NULL;
10972         rsurface.batchelement3s_bufferoffset = 0;
10973         rsurface.passcolor4f = NULL;
10974         rsurface.passcolor4f_vertexbuffer = NULL;
10975         rsurface.passcolor4f_bufferoffset = 0;
10976 }
10977
10978 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10979 {
10980         int newvertices;
10981         dp_model_t *model = ent->model;
10982         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10983         //      return;
10984         rsurface.entity = (entity_render_t *)ent;
10985         rsurface.skeleton = ent->skeleton;
10986         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10987         rsurface.ent_skinnum = ent->skinnum;
10988         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;
10989         rsurface.ent_shadertime = ent->shadertime;
10990         rsurface.ent_flags = ent->flags;
10991         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10992         if (rsurface.array_size < newvertices)
10993                 R_Mesh_ResizeArrays(newvertices);
10994         rsurface.matrix = ent->matrix;
10995         rsurface.inversematrix = ent->inversematrix;
10996         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10997         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10998         R_EntityMatrix(&rsurface.matrix);
10999         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11000         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11001         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11002         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11003         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11004         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11005         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11006         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11007         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11008         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11009         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11010         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11011         rsurface.colormod[3] = ent->alpha;
11012         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11013         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11014         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11015         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11016         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11017         if (ent->model->brush.submodel && !prepass)
11018         {
11019                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11020                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11021         }
11022         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11023         {
11024                 if (ent->animcache_vertex3f && !r_framedata_failed)
11025                 {
11026                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11027                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11028                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11029                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11030                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11031                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11032                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11033                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11034                 }
11035                 else if (wanttangents)
11036                 {
11037                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11038                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11039                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11040                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11041                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11042                         rsurface.modelvertexmesh = NULL;
11043                         rsurface.modelvertexmeshbuffer = NULL;
11044                         rsurface.modelvertexposition = NULL;
11045                         rsurface.modelvertexpositionbuffer = NULL;
11046                 }
11047                 else if (wantnormals)
11048                 {
11049                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11050                         rsurface.modelsvector3f = NULL;
11051                         rsurface.modeltvector3f = NULL;
11052                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11053                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11054                         rsurface.modelvertexmesh = NULL;
11055                         rsurface.modelvertexmeshbuffer = NULL;
11056                         rsurface.modelvertexposition = NULL;
11057                         rsurface.modelvertexpositionbuffer = NULL;
11058                 }
11059                 else
11060                 {
11061                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11062                         rsurface.modelsvector3f = NULL;
11063                         rsurface.modeltvector3f = NULL;
11064                         rsurface.modelnormal3f = NULL;
11065                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11066                         rsurface.modelvertexmesh = NULL;
11067                         rsurface.modelvertexmeshbuffer = NULL;
11068                         rsurface.modelvertexposition = NULL;
11069                         rsurface.modelvertexpositionbuffer = NULL;
11070                 }
11071                 rsurface.modelvertex3f_vertexbuffer = 0;
11072                 rsurface.modelvertex3f_bufferoffset = 0;
11073                 rsurface.modelsvector3f_vertexbuffer = 0;
11074                 rsurface.modelsvector3f_bufferoffset = 0;
11075                 rsurface.modeltvector3f_vertexbuffer = 0;
11076                 rsurface.modeltvector3f_bufferoffset = 0;
11077                 rsurface.modelnormal3f_vertexbuffer = 0;
11078                 rsurface.modelnormal3f_bufferoffset = 0;
11079                 rsurface.modelgeneratedvertex = true;
11080         }
11081         else
11082         {
11083                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11084                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11085                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11086                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11087                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11088                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11089                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11090                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11091                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11092                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11093                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11094                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11095                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11096                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11097                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11098                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11099                 rsurface.modelgeneratedvertex = false;
11100         }
11101         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11102         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11103         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11104         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11105         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11106         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11107         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11108         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11109         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11110         rsurface.modelelement3i = model->surfmesh.data_element3i;
11111         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11112         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11113         rsurface.modelelement3s = model->surfmesh.data_element3s;
11114         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11115         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11116         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11117         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11118         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11119         rsurface.modelsurfaces = model->data_surfaces;
11120         rsurface.batchgeneratedvertex = false;
11121         rsurface.batchfirstvertex = 0;
11122         rsurface.batchnumvertices = 0;
11123         rsurface.batchfirsttriangle = 0;
11124         rsurface.batchnumtriangles = 0;
11125         rsurface.batchvertex3f  = NULL;
11126         rsurface.batchvertex3f_vertexbuffer = NULL;
11127         rsurface.batchvertex3f_bufferoffset = 0;
11128         rsurface.batchsvector3f = NULL;
11129         rsurface.batchsvector3f_vertexbuffer = NULL;
11130         rsurface.batchsvector3f_bufferoffset = 0;
11131         rsurface.batchtvector3f = NULL;
11132         rsurface.batchtvector3f_vertexbuffer = NULL;
11133         rsurface.batchtvector3f_bufferoffset = 0;
11134         rsurface.batchnormal3f  = NULL;
11135         rsurface.batchnormal3f_vertexbuffer = NULL;
11136         rsurface.batchnormal3f_bufferoffset = 0;
11137         rsurface.batchlightmapcolor4f = NULL;
11138         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11139         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11140         rsurface.batchtexcoordtexture2f = NULL;
11141         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11142         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11143         rsurface.batchtexcoordlightmap2f = NULL;
11144         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11145         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11146         rsurface.batchvertexmesh = NULL;
11147         rsurface.batchvertexmeshbuffer = NULL;
11148         rsurface.batchvertexposition = NULL;
11149         rsurface.batchvertexpositionbuffer = NULL;
11150         rsurface.batchelement3i = NULL;
11151         rsurface.batchelement3i_indexbuffer = NULL;
11152         rsurface.batchelement3i_bufferoffset = 0;
11153         rsurface.batchelement3s = NULL;
11154         rsurface.batchelement3s_indexbuffer = NULL;
11155         rsurface.batchelement3s_bufferoffset = 0;
11156         rsurface.passcolor4f = NULL;
11157         rsurface.passcolor4f_vertexbuffer = NULL;
11158         rsurface.passcolor4f_bufferoffset = 0;
11159 }
11160
11161 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)
11162 {
11163         int newvertices;
11164
11165         rsurface.entity = r_refdef.scene.worldentity;
11166         rsurface.skeleton = NULL;
11167         rsurface.ent_skinnum = 0;
11168         rsurface.ent_qwskin = -1;
11169         rsurface.ent_shadertime = shadertime;
11170         rsurface.ent_flags = entflags;
11171         rsurface.modelnumvertices = numvertices;
11172         rsurface.modelnumtriangles = numtriangles;
11173         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11174         if (rsurface.array_size < newvertices)
11175                 R_Mesh_ResizeArrays(newvertices);
11176         rsurface.matrix = *matrix;
11177         rsurface.inversematrix = *inversematrix;
11178         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11179         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11180         R_EntityMatrix(&rsurface.matrix);
11181         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11182         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11183         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11184         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11185         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11186         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11187         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11188         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11189         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11190         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11191         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11192         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11193         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);
11194         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11195         rsurface.frameblend[0].lerp = 1;
11196         rsurface.ent_alttextures = false;
11197         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11198         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11199         if (wanttangents)
11200         {
11201                 rsurface.modelvertex3f = vertex3f;
11202                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11203                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11204                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11205         }
11206         else if (wantnormals)
11207         {
11208                 rsurface.modelvertex3f = vertex3f;
11209                 rsurface.modelsvector3f = NULL;
11210                 rsurface.modeltvector3f = NULL;
11211                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11212         }
11213         else
11214         {
11215                 rsurface.modelvertex3f = vertex3f;
11216                 rsurface.modelsvector3f = NULL;
11217                 rsurface.modeltvector3f = NULL;
11218                 rsurface.modelnormal3f = NULL;
11219         }
11220         rsurface.modelvertexmesh = NULL;
11221         rsurface.modelvertexmeshbuffer = NULL;
11222         rsurface.modelvertexposition = NULL;
11223         rsurface.modelvertexpositionbuffer = NULL;
11224         rsurface.modelvertex3f_vertexbuffer = 0;
11225         rsurface.modelvertex3f_bufferoffset = 0;
11226         rsurface.modelsvector3f_vertexbuffer = 0;
11227         rsurface.modelsvector3f_bufferoffset = 0;
11228         rsurface.modeltvector3f_vertexbuffer = 0;
11229         rsurface.modeltvector3f_bufferoffset = 0;
11230         rsurface.modelnormal3f_vertexbuffer = 0;
11231         rsurface.modelnormal3f_bufferoffset = 0;
11232         rsurface.modelgeneratedvertex = true;
11233         rsurface.modellightmapcolor4f  = color4f;
11234         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11235         rsurface.modellightmapcolor4f_bufferoffset = 0;
11236         rsurface.modeltexcoordtexture2f  = texcoord2f;
11237         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11238         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11239         rsurface.modeltexcoordlightmap2f  = NULL;
11240         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11241         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11242         rsurface.modelelement3i = element3i;
11243         rsurface.modelelement3i_indexbuffer = NULL;
11244         rsurface.modelelement3i_bufferoffset = 0;
11245         rsurface.modelelement3s = element3s;
11246         rsurface.modelelement3s_indexbuffer = NULL;
11247         rsurface.modelelement3s_bufferoffset = 0;
11248         rsurface.modellightmapoffsets = NULL;
11249         rsurface.modelsurfaces = NULL;
11250         rsurface.batchgeneratedvertex = false;
11251         rsurface.batchfirstvertex = 0;
11252         rsurface.batchnumvertices = 0;
11253         rsurface.batchfirsttriangle = 0;
11254         rsurface.batchnumtriangles = 0;
11255         rsurface.batchvertex3f  = NULL;
11256         rsurface.batchvertex3f_vertexbuffer = NULL;
11257         rsurface.batchvertex3f_bufferoffset = 0;
11258         rsurface.batchsvector3f = NULL;
11259         rsurface.batchsvector3f_vertexbuffer = NULL;
11260         rsurface.batchsvector3f_bufferoffset = 0;
11261         rsurface.batchtvector3f = NULL;
11262         rsurface.batchtvector3f_vertexbuffer = NULL;
11263         rsurface.batchtvector3f_bufferoffset = 0;
11264         rsurface.batchnormal3f  = NULL;
11265         rsurface.batchnormal3f_vertexbuffer = NULL;
11266         rsurface.batchnormal3f_bufferoffset = 0;
11267         rsurface.batchlightmapcolor4f = NULL;
11268         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11269         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11270         rsurface.batchtexcoordtexture2f = NULL;
11271         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11272         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11273         rsurface.batchtexcoordlightmap2f = NULL;
11274         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11275         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11276         rsurface.batchvertexmesh = NULL;
11277         rsurface.batchvertexmeshbuffer = NULL;
11278         rsurface.batchvertexposition = NULL;
11279         rsurface.batchvertexpositionbuffer = NULL;
11280         rsurface.batchelement3i = NULL;
11281         rsurface.batchelement3i_indexbuffer = NULL;
11282         rsurface.batchelement3i_bufferoffset = 0;
11283         rsurface.batchelement3s = NULL;
11284         rsurface.batchelement3s_indexbuffer = NULL;
11285         rsurface.batchelement3s_bufferoffset = 0;
11286         rsurface.passcolor4f = NULL;
11287         rsurface.passcolor4f_vertexbuffer = NULL;
11288         rsurface.passcolor4f_bufferoffset = 0;
11289
11290         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11291         {
11292                 if ((wantnormals || wanttangents) && !normal3f)
11293                 {
11294                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11295                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11296                 }
11297                 if (wanttangents && !svector3f)
11298                 {
11299                         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);
11300                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11301                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11302                 }
11303         }
11304 }
11305
11306 float RSurf_FogPoint(const float *v)
11307 {
11308         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11309         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11310         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11311         float FogHeightFade = r_refdef.fogheightfade;
11312         float fogfrac;
11313         unsigned int fogmasktableindex;
11314         if (r_refdef.fogplaneviewabove)
11315                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11316         else
11317                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11318         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11319         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11320 }
11321
11322 float RSurf_FogVertex(const float *v)
11323 {
11324         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11325         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11326         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11327         float FogHeightFade = rsurface.fogheightfade;
11328         float fogfrac;
11329         unsigned int fogmasktableindex;
11330         if (r_refdef.fogplaneviewabove)
11331                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11332         else
11333                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11334         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11335         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11336 }
11337
11338 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11339 {
11340         int i;
11341         for (i = 0;i < numelements;i++)
11342                 outelement3i[i] = inelement3i[i] + adjust;
11343 }
11344
11345 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11346 extern cvar_t gl_vbo;
11347 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11348 {
11349         int deformindex;
11350         int firsttriangle;
11351         int numtriangles;
11352         int firstvertex;
11353         int endvertex;
11354         int numvertices;
11355         int surfacefirsttriangle;
11356         int surfacenumtriangles;
11357         int surfacefirstvertex;
11358         int surfaceendvertex;
11359         int surfacenumvertices;
11360         int needsupdate;
11361         int i, j;
11362         qboolean gaps;
11363         qboolean dynamicvertex;
11364         float amplitude;
11365         float animpos;
11366         float scale;
11367         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11368         float waveparms[4];
11369         q3shaderinfo_deform_t *deform;
11370         const msurface_t *surface, *firstsurface;
11371         r_vertexposition_t *vertexposition;
11372         r_vertexmesh_t *vertexmesh;
11373         if (!texturenumsurfaces)
11374                 return;
11375         // find vertex range of this surface batch
11376         gaps = false;
11377         firstsurface = texturesurfacelist[0];
11378         firsttriangle = firstsurface->num_firsttriangle;
11379         numtriangles = 0;
11380         firstvertex = endvertex = firstsurface->num_firstvertex;
11381         for (i = 0;i < texturenumsurfaces;i++)
11382         {
11383                 surface = texturesurfacelist[i];
11384                 if (surface != firstsurface + i)
11385                         gaps = true;
11386                 surfacefirstvertex = surface->num_firstvertex;
11387                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11388                 surfacenumtriangles = surface->num_triangles;
11389                 if (firstvertex > surfacefirstvertex)
11390                         firstvertex = surfacefirstvertex;
11391                 if (endvertex < surfaceendvertex)
11392                         endvertex = surfaceendvertex;
11393                 numtriangles += surfacenumtriangles;
11394         }
11395
11396         // we now know the vertex range used, and if there are any gaps in it
11397         rsurface.batchfirstvertex = firstvertex;
11398         rsurface.batchnumvertices = endvertex - firstvertex;
11399         rsurface.batchfirsttriangle = firsttriangle;
11400         rsurface.batchnumtriangles = numtriangles;
11401
11402         // this variable holds flags for which properties have been updated that
11403         // may require regenerating vertexmesh or vertexposition arrays...
11404         needsupdate = 0;
11405
11406         // check if any dynamic vertex processing must occur
11407         dynamicvertex = false;
11408
11409         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11410                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11411         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11412         {
11413                 switch (deform->deform)
11414                 {
11415                 default:
11416                 case Q3DEFORM_PROJECTIONSHADOW:
11417                 case Q3DEFORM_TEXT0:
11418                 case Q3DEFORM_TEXT1:
11419                 case Q3DEFORM_TEXT2:
11420                 case Q3DEFORM_TEXT3:
11421                 case Q3DEFORM_TEXT4:
11422                 case Q3DEFORM_TEXT5:
11423                 case Q3DEFORM_TEXT6:
11424                 case Q3DEFORM_TEXT7:
11425                 case Q3DEFORM_NONE:
11426                         break;
11427                 case Q3DEFORM_AUTOSPRITE:
11428                         dynamicvertex = true;
11429                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11430                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11431                         break;
11432                 case Q3DEFORM_AUTOSPRITE2:
11433                         dynamicvertex = true;
11434                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11435                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11436                         break;
11437                 case Q3DEFORM_NORMAL:
11438                         dynamicvertex = true;
11439                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11440                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11441                         break;
11442                 case Q3DEFORM_WAVE:
11443                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11444                                 break; // if wavefunc is a nop, ignore this transform
11445                         dynamicvertex = true;
11446                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11447                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11448                         break;
11449                 case Q3DEFORM_BULGE:
11450                         dynamicvertex = true;
11451                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11452                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11453                         break;
11454                 case Q3DEFORM_MOVE:
11455                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11456                                 break; // if wavefunc is a nop, ignore this transform
11457                         dynamicvertex = true;
11458                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11459                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11460                         break;
11461                 }
11462         }
11463         switch(rsurface.texture->tcgen.tcgen)
11464         {
11465         default:
11466         case Q3TCGEN_TEXTURE:
11467                 break;
11468         case Q3TCGEN_LIGHTMAP:
11469                 dynamicvertex = true;
11470                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11471                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11472                 break;
11473         case Q3TCGEN_VECTOR:
11474                 dynamicvertex = true;
11475                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11476                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11477                 break;
11478         case Q3TCGEN_ENVIRONMENT:
11479                 dynamicvertex = true;
11480                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11481                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11482                 break;
11483         }
11484         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11485         {
11486                 dynamicvertex = true;
11487                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11488                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11489         }
11490
11491         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11492         {
11493                 dynamicvertex = true;
11494                 batchneed |= BATCHNEED_NOGAPS;
11495                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11496         }
11497
11498         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11499         {
11500                 dynamicvertex = true;
11501                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11502                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11503         }
11504
11505         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11506         {
11507                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11508                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11509                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11510                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11511                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11512                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11513                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11514         }
11515
11516         // when the model data has no vertex buffer (dynamic mesh), we need to
11517         // eliminate gaps
11518         if (!rsurface.modelvertexmeshbuffer)
11519                 batchneed |= BATCHNEED_NOGAPS;
11520
11521         // if needsupdate, we have to do a dynamic vertex batch for sure
11522         if (needsupdate & batchneed)
11523                 dynamicvertex = true;
11524
11525         // see if we need to build vertexmesh from arrays
11526         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11527                 dynamicvertex = true;
11528
11529         // see if we need to build vertexposition from arrays
11530         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11531                 dynamicvertex = true;
11532
11533         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11534         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11535                 dynamicvertex = true;
11536
11537         // if there is a chance of animated vertex colors, it's a dynamic batch
11538         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11539                 dynamicvertex = true;
11540
11541         rsurface.batchvertex3f = rsurface.modelvertex3f;
11542         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11543         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11544         rsurface.batchsvector3f = rsurface.modelsvector3f;
11545         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11546         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11547         rsurface.batchtvector3f = rsurface.modeltvector3f;
11548         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11549         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11550         rsurface.batchnormal3f = rsurface.modelnormal3f;
11551         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11552         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11553         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11554         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11555         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11556         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11557         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11558         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11559         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11560         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11561         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11562         rsurface.batchvertexposition = rsurface.modelvertexposition;
11563         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11564         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11565         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11566         rsurface.batchelement3i = rsurface.modelelement3i;
11567         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11568         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11569         rsurface.batchelement3s = rsurface.modelelement3s;
11570         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11571         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11572
11573         // if any dynamic vertex processing has to occur in software, we copy the
11574         // entire surface list together before processing to rebase the vertices
11575         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11576         //
11577         // if any gaps exist and we do not have a static vertex buffer, we have to
11578         // copy the surface list together to avoid wasting upload bandwidth on the
11579         // vertices in the gaps.
11580         //
11581         // if gaps exist and we have a static vertex buffer, we still have to
11582         // combine the index buffer ranges into one dynamic index buffer.
11583         //
11584         // in all cases we end up with data that can be drawn in one call.
11585
11586         if (!dynamicvertex)
11587         {
11588                 // static vertex data, just set pointers...
11589                 rsurface.batchgeneratedvertex = false;
11590                 // if there are gaps, we want to build a combined index buffer,
11591                 // otherwise use the original static buffer with an appropriate offset
11592                 if (gaps)
11593                 {
11594                         firsttriangle = 0;
11595                         numtriangles = 0;
11596                         for (i = 0;i < texturenumsurfaces;i++)
11597                         {
11598                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11599                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11600                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11601                                 numtriangles += surfacenumtriangles;
11602                         }
11603                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11604                         rsurface.batchelement3i_indexbuffer = NULL;
11605                         rsurface.batchelement3i_bufferoffset = 0;
11606                         rsurface.batchelement3s = NULL;
11607                         rsurface.batchelement3s_indexbuffer = NULL;
11608                         rsurface.batchelement3s_bufferoffset = 0;
11609                         if (endvertex <= 65536)
11610                         {
11611                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11612                                 for (i = 0;i < numtriangles*3;i++)
11613                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11614                         }
11615                         rsurface.batchfirsttriangle = firsttriangle;
11616                         rsurface.batchnumtriangles = numtriangles;
11617                 }
11618                 return;
11619         }
11620
11621         // something needs software processing, do it for real...
11622         // we only directly handle interleaved array data in this case...
11623         rsurface.batchgeneratedvertex = true;
11624
11625         // now copy the vertex data into a combined array and make an index array
11626         // (this is what Quake3 does all the time)
11627         //if (gaps || rsurface.batchfirstvertex)
11628         {
11629                 rsurface.batchvertexposition = NULL;
11630                 rsurface.batchvertexpositionbuffer = NULL;
11631                 rsurface.batchvertexmesh = NULL;
11632                 rsurface.batchvertexmeshbuffer = NULL;
11633                 rsurface.batchvertex3f = NULL;
11634                 rsurface.batchvertex3f_vertexbuffer = NULL;
11635                 rsurface.batchvertex3f_bufferoffset = 0;
11636                 rsurface.batchsvector3f = NULL;
11637                 rsurface.batchsvector3f_vertexbuffer = NULL;
11638                 rsurface.batchsvector3f_bufferoffset = 0;
11639                 rsurface.batchtvector3f = NULL;
11640                 rsurface.batchtvector3f_vertexbuffer = NULL;
11641                 rsurface.batchtvector3f_bufferoffset = 0;
11642                 rsurface.batchnormal3f = NULL;
11643                 rsurface.batchnormal3f_vertexbuffer = NULL;
11644                 rsurface.batchnormal3f_bufferoffset = 0;
11645                 rsurface.batchlightmapcolor4f = NULL;
11646                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11647                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11648                 rsurface.batchtexcoordtexture2f = NULL;
11649                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11650                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11651                 rsurface.batchtexcoordlightmap2f = NULL;
11652                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11653                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11654                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11655                 rsurface.batchelement3i_indexbuffer = NULL;
11656                 rsurface.batchelement3i_bufferoffset = 0;
11657                 rsurface.batchelement3s = NULL;
11658                 rsurface.batchelement3s_indexbuffer = NULL;
11659                 rsurface.batchelement3s_bufferoffset = 0;
11660                 // we'll only be setting up certain arrays as needed
11661                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11662                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11663                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11664                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11665                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11666                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11667                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11668                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11669                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11670                 {
11671                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11672                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11673                 }
11674                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11675                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11676                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11677                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11678                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11679                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11680                 numvertices = 0;
11681                 numtriangles = 0;
11682                 for (i = 0;i < texturenumsurfaces;i++)
11683                 {
11684                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11685                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11686                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11687                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11688                         // copy only the data requested
11689                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11690                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11691                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11692                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11693                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11694                         {
11695                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11696                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11697                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11698                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11699                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11700                                 {
11701                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11702                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11703                                 }
11704                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11705                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11706                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11707                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11708                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11709                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11710                         }
11711                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11712                         numvertices += surfacenumvertices;
11713                         numtriangles += surfacenumtriangles;
11714                 }
11715
11716                 // generate a 16bit index array as well if possible
11717                 // (in general, dynamic batches fit)
11718                 if (numvertices <= 65536)
11719                 {
11720                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11721                         for (i = 0;i < numtriangles*3;i++)
11722                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11723                 }
11724
11725                 // since we've copied everything, the batch now starts at 0
11726                 rsurface.batchfirstvertex = 0;
11727                 rsurface.batchnumvertices = numvertices;
11728                 rsurface.batchfirsttriangle = 0;
11729                 rsurface.batchnumtriangles = numtriangles;
11730         }
11731
11732         // q1bsp surfaces rendered in vertex color mode have to have colors
11733         // calculated based on lightstyles
11734         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11735         {
11736                 // generate color arrays for the surfaces in this list
11737                 int c[4];
11738                 int scale;
11739                 int size3;
11740                 const int *offsets;
11741                 const unsigned char *lm;
11742                 numvertices = 0;
11743                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11744                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11745                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11746                 for (i = 0;i < texturenumsurfaces;i++)
11747                 {
11748                         surface = texturesurfacelist[i];
11749                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11750                         surfacenumvertices = surface->num_vertices;
11751                         if (surface->lightmapinfo->samples)
11752                         {
11753                                 for (j = 0;j < surfacenumvertices;j++)
11754                                 {
11755                                         lm = surface->lightmapinfo->samples + offsets[j];
11756                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11757                                         VectorScale(lm, scale, c);
11758                                         if (surface->lightmapinfo->styles[1] != 255)
11759                                         {
11760                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11761                                                 lm += size3;
11762                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11763                                                 VectorMA(c, scale, lm, c);
11764                                                 if (surface->lightmapinfo->styles[2] != 255)
11765                                                 {
11766                                                         lm += size3;
11767                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11768                                                         VectorMA(c, scale, lm, c);
11769                                                         if (surface->lightmapinfo->styles[3] != 255)
11770                                                         {
11771                                                                 lm += size3;
11772                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11773                                                                 VectorMA(c, scale, lm, c);
11774                                                         }
11775                                                 }
11776                                         }
11777                                         c[0] >>= 15;
11778                                         c[1] >>= 15;
11779                                         c[2] >>= 15;
11780                                         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);
11781                                         numvertices++;
11782                                 }
11783                         }
11784                         else
11785                         {
11786                                 for (j = 0;j < surfacenumvertices;j++)
11787                                 {
11788                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11789                                         numvertices++;
11790                                 }
11791                         }
11792                 }
11793         }
11794
11795         // if vertices are deformed (sprite flares and things in maps, possibly
11796         // water waves, bulges and other deformations), modify the copied vertices
11797         // in place
11798         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11799         {
11800                 switch (deform->deform)
11801                 {
11802                 default:
11803                 case Q3DEFORM_PROJECTIONSHADOW:
11804                 case Q3DEFORM_TEXT0:
11805                 case Q3DEFORM_TEXT1:
11806                 case Q3DEFORM_TEXT2:
11807                 case Q3DEFORM_TEXT3:
11808                 case Q3DEFORM_TEXT4:
11809                 case Q3DEFORM_TEXT5:
11810                 case Q3DEFORM_TEXT6:
11811                 case Q3DEFORM_TEXT7:
11812                 case Q3DEFORM_NONE:
11813                         break;
11814                 case Q3DEFORM_AUTOSPRITE:
11815                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11816                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11817                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11818                         VectorNormalize(newforward);
11819                         VectorNormalize(newright);
11820                         VectorNormalize(newup);
11821                         // a single autosprite surface can contain multiple sprites...
11822                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11823                         {
11824                                 VectorClear(center);
11825                                 for (i = 0;i < 4;i++)
11826                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11827                                 VectorScale(center, 0.25f, center);
11828                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11829                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11830                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11831                                 for (i = 0;i < 4;i++)
11832                                 {
11833                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11834                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11835                                 }
11836                         }
11837                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11838                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11839                         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);
11840                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11841                         rsurface.batchvertex3f_vertexbuffer = NULL;
11842                         rsurface.batchvertex3f_bufferoffset = 0;
11843                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11844                         rsurface.batchsvector3f_vertexbuffer = NULL;
11845                         rsurface.batchsvector3f_bufferoffset = 0;
11846                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11847                         rsurface.batchtvector3f_vertexbuffer = NULL;
11848                         rsurface.batchtvector3f_bufferoffset = 0;
11849                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11850                         rsurface.batchnormal3f_vertexbuffer = NULL;
11851                         rsurface.batchnormal3f_bufferoffset = 0;
11852                         break;
11853                 case Q3DEFORM_AUTOSPRITE2:
11854                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11855                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11856                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11857                         VectorNormalize(newforward);
11858                         VectorNormalize(newright);
11859                         VectorNormalize(newup);
11860                         {
11861                                 const float *v1, *v2;
11862                                 vec3_t start, end;
11863                                 float f, l;
11864                                 struct
11865                                 {
11866                                         float length2;
11867                                         const float *v1;
11868                                         const float *v2;
11869                                 }
11870                                 shortest[2];
11871                                 memset(shortest, 0, sizeof(shortest));
11872                                 // a single autosprite surface can contain multiple sprites...
11873                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11874                                 {
11875                                         VectorClear(center);
11876                                         for (i = 0;i < 4;i++)
11877                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11878                                         VectorScale(center, 0.25f, center);
11879                                         // find the two shortest edges, then use them to define the
11880                                         // axis vectors for rotating around the central axis
11881                                         for (i = 0;i < 6;i++)
11882                                         {
11883                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11884                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11885                                                 l = VectorDistance2(v1, v2);
11886                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11887                                                 if (v1[2] != v2[2])
11888                                                         l += (1.0f / 1024.0f);
11889                                                 if (shortest[0].length2 > l || i == 0)
11890                                                 {
11891                                                         shortest[1] = shortest[0];
11892                                                         shortest[0].length2 = l;
11893                                                         shortest[0].v1 = v1;
11894                                                         shortest[0].v2 = v2;
11895                                                 }
11896                                                 else if (shortest[1].length2 > l || i == 1)
11897                                                 {
11898                                                         shortest[1].length2 = l;
11899                                                         shortest[1].v1 = v1;
11900                                                         shortest[1].v2 = v2;
11901                                                 }
11902                                         }
11903                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11904                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11905                                         // this calculates the right vector from the shortest edge
11906                                         // and the up vector from the edge midpoints
11907                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11908                                         VectorNormalize(right);
11909                                         VectorSubtract(end, start, up);
11910                                         VectorNormalize(up);
11911                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11912                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11913                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11914                                         VectorNegate(forward, forward);
11915                                         VectorReflect(forward, 0, up, forward);
11916                                         VectorNormalize(forward);
11917                                         CrossProduct(up, forward, newright);
11918                                         VectorNormalize(newright);
11919                                         // rotate the quad around the up axis vector, this is made
11920                                         // especially easy by the fact we know the quad is flat,
11921                                         // so we only have to subtract the center position and
11922                                         // measure distance along the right vector, and then
11923                                         // multiply that by the newright vector and add back the
11924                                         // center position
11925                                         // we also need to subtract the old position to undo the
11926                                         // displacement from the center, which we do with a
11927                                         // DotProduct, the subtraction/addition of center is also
11928                                         // optimized into DotProducts here
11929                                         l = DotProduct(right, center);
11930                                         for (i = 0;i < 4;i++)
11931                                         {
11932                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11933                                                 f = DotProduct(right, v1) - l;
11934                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11935                                         }
11936                                 }
11937                         }
11938                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11939                         rsurface.batchvertex3f_vertexbuffer = NULL;
11940                         rsurface.batchvertex3f_bufferoffset = 0;
11941                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11942                         {
11943                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11944                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11945                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11946                                 rsurface.batchnormal3f_bufferoffset = 0;
11947                         }
11948                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11949                         {
11950                                 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);
11951                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11952                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11953                                 rsurface.batchsvector3f_bufferoffset = 0;
11954                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11955                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11956                                 rsurface.batchtvector3f_bufferoffset = 0;
11957                         }
11958                         break;
11959                 case Q3DEFORM_NORMAL:
11960                         // deform the normals to make reflections wavey
11961                         for (j = 0;j < rsurface.batchnumvertices;j++)
11962                         {
11963                                 float vertex[3];
11964                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11965                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11966                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11967                                 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]);
11968                                 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]);
11969                                 VectorNormalize(normal);
11970                         }
11971                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11972                         rsurface.batchnormal3f_vertexbuffer = NULL;
11973                         rsurface.batchnormal3f_bufferoffset = 0;
11974                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11975                         {
11976                                 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);
11977                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11978                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11979                                 rsurface.batchsvector3f_bufferoffset = 0;
11980                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11981                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11982                                 rsurface.batchtvector3f_bufferoffset = 0;
11983                         }
11984                         break;
11985                 case Q3DEFORM_WAVE:
11986                         // deform vertex array to make wavey water and flags and such
11987                         waveparms[0] = deform->waveparms[0];
11988                         waveparms[1] = deform->waveparms[1];
11989                         waveparms[2] = deform->waveparms[2];
11990                         waveparms[3] = deform->waveparms[3];
11991                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11992                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11993                         // this is how a divisor of vertex influence on deformation
11994                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11995                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11996                         for (j = 0;j < rsurface.batchnumvertices;j++)
11997                         {
11998                                 // if the wavefunc depends on time, evaluate it per-vertex
11999                                 if (waveparms[3])
12000                                 {
12001                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12002                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12003                                 }
12004                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12005                         }
12006                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12007                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12008                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12009                         rsurface.batchvertex3f_vertexbuffer = NULL;
12010                         rsurface.batchvertex3f_bufferoffset = 0;
12011                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12012                         rsurface.batchnormal3f_vertexbuffer = NULL;
12013                         rsurface.batchnormal3f_bufferoffset = 0;
12014                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12015                         {
12016                                 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);
12017                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12018                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12019                                 rsurface.batchsvector3f_bufferoffset = 0;
12020                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12021                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12022                                 rsurface.batchtvector3f_bufferoffset = 0;
12023                         }
12024                         break;
12025                 case Q3DEFORM_BULGE:
12026                         // deform vertex array to make the surface have moving bulges
12027                         for (j = 0;j < rsurface.batchnumvertices;j++)
12028                         {
12029                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12030                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12031                         }
12032                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12033                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12034                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12035                         rsurface.batchvertex3f_vertexbuffer = NULL;
12036                         rsurface.batchvertex3f_bufferoffset = 0;
12037                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12038                         rsurface.batchnormal3f_vertexbuffer = NULL;
12039                         rsurface.batchnormal3f_bufferoffset = 0;
12040                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12041                         {
12042                                 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);
12043                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12044                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12045                                 rsurface.batchsvector3f_bufferoffset = 0;
12046                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12047                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12048                                 rsurface.batchtvector3f_bufferoffset = 0;
12049                         }
12050                         break;
12051                 case Q3DEFORM_MOVE:
12052                         // deform vertex array
12053                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12054                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12055                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12056                         VectorScale(deform->parms, scale, waveparms);
12057                         for (j = 0;j < rsurface.batchnumvertices;j++)
12058                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12059                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12060                         rsurface.batchvertex3f_vertexbuffer = NULL;
12061                         rsurface.batchvertex3f_bufferoffset = 0;
12062                         break;
12063                 }
12064         }
12065
12066         // generate texcoords based on the chosen texcoord source
12067         switch(rsurface.texture->tcgen.tcgen)
12068         {
12069         default:
12070         case Q3TCGEN_TEXTURE:
12071                 break;
12072         case Q3TCGEN_LIGHTMAP:
12073                 if (rsurface.batchtexcoordlightmap2f)
12074                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12075                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12076                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12077                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12078                 break;
12079         case Q3TCGEN_VECTOR:
12080                 for (j = 0;j < rsurface.batchnumvertices;j++)
12081                 {
12082                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12083                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12084                 }
12085                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12086                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12087                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12088                 break;
12089         case Q3TCGEN_ENVIRONMENT:
12090                 // make environment reflections using a spheremap
12091                 for (j = 0;j < rsurface.batchnumvertices;j++)
12092                 {
12093                         // identical to Q3A's method, but executed in worldspace so
12094                         // carried models can be shiny too
12095
12096                         float viewer[3], d, reflected[3], worldreflected[3];
12097
12098                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12099                         // VectorNormalize(viewer);
12100
12101                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12102
12103                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12104                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12105                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12106                         // note: this is proportinal to viewer, so we can normalize later
12107
12108                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12109                         VectorNormalize(worldreflected);
12110
12111                         // note: this sphere map only uses world x and z!
12112                         // so positive and negative y will LOOK THE SAME.
12113                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12114                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12115                 }
12116                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12117                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12118                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12119                 break;
12120         }
12121         // the only tcmod that needs software vertex processing is turbulent, so
12122         // check for it here and apply the changes if needed
12123         // and we only support that as the first one
12124         // (handling a mixture of turbulent and other tcmods would be problematic
12125         //  without punting it entirely to a software path)
12126         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12127         {
12128                 amplitude = rsurface.texture->tcmods[0].parms[1];
12129                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12130                 for (j = 0;j < rsurface.batchnumvertices;j++)
12131                 {
12132                         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);
12133                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12134                 }
12135                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12136                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12137                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12138         }
12139
12140         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12141         {
12142                 // convert the modified arrays to vertex structs
12143                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12144                 rsurface.batchvertexmeshbuffer = NULL;
12145                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12146                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12147                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12148                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12149                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12150                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12151                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12152                 {
12153                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12154                         {
12155                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12156                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12157                         }
12158                 }
12159                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12160                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12161                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12162                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12163                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12164                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12165                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12166                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12167                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12168         }
12169
12170         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12171         {
12172                 // convert the modified arrays to vertex structs
12173                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12174                 rsurface.batchvertexpositionbuffer = NULL;
12175                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12176                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12177                 else
12178                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12179                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12180         }
12181 }
12182
12183 void RSurf_DrawBatch(void)
12184 {
12185         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12186         // through the pipeline, killing it earlier in the pipeline would have
12187         // per-surface overhead rather than per-batch overhead, so it's best to
12188         // reject it here, before it hits glDraw.
12189         if (rsurface.batchnumtriangles == 0)
12190                 return;
12191 #if 0
12192         // batch debugging code
12193         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12194         {
12195                 int i;
12196                 int j;
12197                 int c;
12198                 const int *e;
12199                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12200                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12201                 {
12202                         c = e[i];
12203                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12204                         {
12205                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12206                                 {
12207                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12208                                                 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);
12209                                         break;
12210                                 }
12211                         }
12212                 }
12213         }
12214 #endif
12215         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);
12216 }
12217
12218 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12219 {
12220         // pick the closest matching water plane
12221         int planeindex, vertexindex, bestplaneindex = -1;
12222         float d, bestd;
12223         vec3_t vert;
12224         const float *v;
12225         r_waterstate_waterplane_t *p;
12226         bestd = 0;
12227         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12228         {
12229                 if(p->camera_entity != rsurface.texture->camera_entity)
12230                         continue;
12231                 d = 0;
12232                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12233                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12234                 {
12235                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12236                         d += fabs(PlaneDiff(vert, &p->plane));
12237                 }
12238                 if (bestd > d || bestplaneindex < 0)
12239                 {
12240                         bestd = d;
12241                         bestplaneindex = planeindex;
12242                 }
12243         }
12244         return bestplaneindex;
12245 }
12246
12247 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12248 {
12249         int i;
12250         for (i = 0;i < rsurface.batchnumvertices;i++)
12251                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12252         rsurface.passcolor4f = rsurface.array_passcolor4f;
12253         rsurface.passcolor4f_vertexbuffer = 0;
12254         rsurface.passcolor4f_bufferoffset = 0;
12255 }
12256
12257 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12258 {
12259         int i;
12260         float f;
12261         const float *v;
12262         const float *c;
12263         float *c2;
12264         if (rsurface.passcolor4f)
12265         {
12266                 // generate color arrays
12267                 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)
12268                 {
12269                         f = RSurf_FogVertex(v);
12270                         c2[0] = c[0] * f;
12271                         c2[1] = c[1] * f;
12272                         c2[2] = c[2] * f;
12273                         c2[3] = c[3];
12274                 }
12275         }
12276         else
12277         {
12278                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12279                 {
12280                         f = RSurf_FogVertex(v);
12281                         c2[0] = f;
12282                         c2[1] = f;
12283                         c2[2] = f;
12284                         c2[3] = 1;
12285                 }
12286         }
12287         rsurface.passcolor4f = rsurface.array_passcolor4f;
12288         rsurface.passcolor4f_vertexbuffer = 0;
12289         rsurface.passcolor4f_bufferoffset = 0;
12290 }
12291
12292 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12293 {
12294         int i;
12295         float f;
12296         const float *v;
12297         const float *c;
12298         float *c2;
12299         if (!rsurface.passcolor4f)
12300                 return;
12301         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)
12302         {
12303                 f = RSurf_FogVertex(v);
12304                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12305                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12306                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12307                 c2[3] = c[3];
12308         }
12309         rsurface.passcolor4f = rsurface.array_passcolor4f;
12310         rsurface.passcolor4f_vertexbuffer = 0;
12311         rsurface.passcolor4f_bufferoffset = 0;
12312 }
12313
12314 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12315 {
12316         int i;
12317         const float *c;
12318         float *c2;
12319         if (!rsurface.passcolor4f)
12320                 return;
12321         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12322         {
12323                 c2[0] = c[0] * r;
12324                 c2[1] = c[1] * g;
12325                 c2[2] = c[2] * b;
12326                 c2[3] = c[3] * a;
12327         }
12328         rsurface.passcolor4f = rsurface.array_passcolor4f;
12329         rsurface.passcolor4f_vertexbuffer = 0;
12330         rsurface.passcolor4f_bufferoffset = 0;
12331 }
12332
12333 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12334 {
12335         int i;
12336         const float *c;
12337         float *c2;
12338         if (!rsurface.passcolor4f)
12339                 return;
12340         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12341         {
12342                 c2[0] = c[0] + r_refdef.scene.ambient;
12343                 c2[1] = c[1] + r_refdef.scene.ambient;
12344                 c2[2] = c[2] + r_refdef.scene.ambient;
12345                 c2[3] = c[3];
12346         }
12347         rsurface.passcolor4f = rsurface.array_passcolor4f;
12348         rsurface.passcolor4f_vertexbuffer = 0;
12349         rsurface.passcolor4f_bufferoffset = 0;
12350 }
12351
12352 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12353 {
12354         // TODO: optimize
12355         rsurface.passcolor4f = NULL;
12356         rsurface.passcolor4f_vertexbuffer = 0;
12357         rsurface.passcolor4f_bufferoffset = 0;
12358         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12359         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12360         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12361         GL_Color(r, g, b, a);
12362         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12363         RSurf_DrawBatch();
12364 }
12365
12366 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12367 {
12368         // TODO: optimize applyfog && applycolor case
12369         // just apply fog if necessary, and tint the fog color array if necessary
12370         rsurface.passcolor4f = NULL;
12371         rsurface.passcolor4f_vertexbuffer = 0;
12372         rsurface.passcolor4f_bufferoffset = 0;
12373         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12374         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12375         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12376         GL_Color(r, g, b, a);
12377         RSurf_DrawBatch();
12378 }
12379
12380 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12381 {
12382         // TODO: optimize
12383         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12384         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12385         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12386         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12387         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12388         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12389         GL_Color(r, g, b, a);
12390         RSurf_DrawBatch();
12391 }
12392
12393 static void RSurf_DrawBatch_GL11_ClampColor(void)
12394 {
12395         int i;
12396         const float *c1;
12397         float *c2;
12398         if (!rsurface.passcolor4f)
12399                 return;
12400         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12401         {
12402                 c2[0] = bound(0.0f, c1[0], 1.0f);
12403                 c2[1] = bound(0.0f, c1[1], 1.0f);
12404                 c2[2] = bound(0.0f, c1[2], 1.0f);
12405                 c2[3] = bound(0.0f, c1[3], 1.0f);
12406         }
12407 }
12408
12409 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12410 {
12411         int i;
12412         float f;
12413         const float *v;
12414         const float *n;
12415         float *c;
12416         //vec3_t eyedir;
12417
12418         // fake shading
12419         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)
12420         {
12421                 f = -DotProduct(r_refdef.view.forward, n);
12422                 f = max(0, f);
12423                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12424                 f *= r_refdef.lightmapintensity;
12425                 Vector4Set(c, f, f, f, 1);
12426         }
12427
12428         rsurface.passcolor4f = rsurface.array_passcolor4f;
12429         rsurface.passcolor4f_vertexbuffer = 0;
12430         rsurface.passcolor4f_bufferoffset = 0;
12431 }
12432
12433 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12434 {
12435         RSurf_DrawBatch_GL11_ApplyFakeLight();
12436         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12437         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12438         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12439         GL_Color(r, g, b, a);
12440         RSurf_DrawBatch();
12441 }
12442
12443 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12444 {
12445         int i;
12446         float f;
12447         float alpha;
12448         const float *v;
12449         const float *n;
12450         float *c;
12451         vec3_t ambientcolor;
12452         vec3_t diffusecolor;
12453         vec3_t lightdir;
12454         // TODO: optimize
12455         // model lighting
12456         VectorCopy(rsurface.modellight_lightdir, lightdir);
12457         f = 0.5f * r_refdef.lightmapintensity;
12458         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12459         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12460         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12461         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12462         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12463         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12464         alpha = *a;
12465         if (VectorLength2(diffusecolor) > 0)
12466         {
12467                 // q3-style directional shading
12468                 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)
12469                 {
12470                         if ((f = DotProduct(n, lightdir)) > 0)
12471                                 VectorMA(ambientcolor, f, diffusecolor, c);
12472                         else
12473                                 VectorCopy(ambientcolor, c);
12474                         c[3] = alpha;
12475                 }
12476                 *r = 1;
12477                 *g = 1;
12478                 *b = 1;
12479                 *a = 1;
12480                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12481                 rsurface.passcolor4f_vertexbuffer = 0;
12482                 rsurface.passcolor4f_bufferoffset = 0;
12483                 *applycolor = false;
12484         }
12485         else
12486         {
12487                 *r = ambientcolor[0];
12488                 *g = ambientcolor[1];
12489                 *b = ambientcolor[2];
12490                 rsurface.passcolor4f = NULL;
12491                 rsurface.passcolor4f_vertexbuffer = 0;
12492                 rsurface.passcolor4f_bufferoffset = 0;
12493         }
12494 }
12495
12496 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12497 {
12498         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12499         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12500         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12501         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12502         GL_Color(r, g, b, a);
12503         RSurf_DrawBatch();
12504 }
12505
12506 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12507 {
12508         int i;
12509         float f;
12510         const float *v;
12511         float *c;
12512         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12513         {
12514                 f = 1 - RSurf_FogVertex(v);
12515                 c[0] = r;
12516                 c[1] = g;
12517                 c[2] = b;
12518                 c[3] = f * a;
12519         }
12520 }
12521
12522 void RSurf_SetupDepthAndCulling(void)
12523 {
12524         // submodels are biased to avoid z-fighting with world surfaces that they
12525         // may be exactly overlapping (avoids z-fighting artifacts on certain
12526         // doors and things in Quake maps)
12527         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12528         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12529         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12530         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12531 }
12532
12533 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12534 {
12535         // transparent sky would be ridiculous
12536         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12537                 return;
12538         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12539         skyrenderlater = true;
12540         RSurf_SetupDepthAndCulling();
12541         GL_DepthMask(true);
12542         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12543         // skymasking on them, and Quake3 never did sky masking (unlike
12544         // software Quake and software Quake2), so disable the sky masking
12545         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12546         // and skymasking also looks very bad when noclipping outside the
12547         // level, so don't use it then either.
12548         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12549         {
12550                 R_Mesh_ResetTextureState();
12551                 if (skyrendermasked)
12552                 {
12553                         R_SetupShader_DepthOrShadow();
12554                         // depth-only (masking)
12555                         GL_ColorMask(0,0,0,0);
12556                         // just to make sure that braindead drivers don't draw
12557                         // anything despite that colormask...
12558                         GL_BlendFunc(GL_ZERO, GL_ONE);
12559                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12560                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12561                 }
12562                 else
12563                 {
12564                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12565                         // fog sky
12566                         GL_BlendFunc(GL_ONE, GL_ZERO);
12567                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12568                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12569                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12570                 }
12571                 RSurf_DrawBatch();
12572                 if (skyrendermasked)
12573                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12574         }
12575         R_Mesh_ResetTextureState();
12576         GL_Color(1, 1, 1, 1);
12577 }
12578
12579 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12580 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12581 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12582 {
12583         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12584                 return;
12585         if (prepass)
12586         {
12587                 // render screenspace normalmap to texture
12588                 GL_DepthMask(true);
12589                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12590                 RSurf_DrawBatch();
12591                 return;
12592         }
12593
12594         // bind lightmap texture
12595
12596         // water/refraction/reflection/camera surfaces have to be handled specially
12597         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12598         {
12599                 int start, end, startplaneindex;
12600                 for (start = 0;start < texturenumsurfaces;start = end)
12601                 {
12602                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12603                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12604                                 ;
12605                         // now that we have a batch using the same planeindex, render it
12606                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12607                         {
12608                                 // render water or distortion background
12609                                 GL_DepthMask(true);
12610                                 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));
12611                                 RSurf_DrawBatch();
12612                                 // blend surface on top
12613                                 GL_DepthMask(false);
12614                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12615                                 RSurf_DrawBatch();
12616                         }
12617                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12618                         {
12619                                 // render surface with reflection texture as input
12620                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12621                                 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));
12622                                 RSurf_DrawBatch();
12623                         }
12624                 }
12625                 return;
12626         }
12627
12628         // render surface batch normally
12629         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12630         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12631         RSurf_DrawBatch();
12632 }
12633
12634 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12635 {
12636         // OpenGL 1.3 path - anything not completely ancient
12637         qboolean applycolor;
12638         qboolean applyfog;
12639         int layerindex;
12640         const texturelayer_t *layer;
12641         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);
12642         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12643
12644         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12645         {
12646                 vec4_t layercolor;
12647                 int layertexrgbscale;
12648                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12649                 {
12650                         if (layerindex == 0)
12651                                 GL_AlphaTest(true);
12652                         else
12653                         {
12654                                 GL_AlphaTest(false);
12655                                 GL_DepthFunc(GL_EQUAL);
12656                         }
12657                 }
12658                 GL_DepthMask(layer->depthmask && writedepth);
12659                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12660                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12661                 {
12662                         layertexrgbscale = 4;
12663                         VectorScale(layer->color, 0.25f, layercolor);
12664                 }
12665                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12666                 {
12667                         layertexrgbscale = 2;
12668                         VectorScale(layer->color, 0.5f, layercolor);
12669                 }
12670                 else
12671                 {
12672                         layertexrgbscale = 1;
12673                         VectorScale(layer->color, 1.0f, layercolor);
12674                 }
12675                 layercolor[3] = layer->color[3];
12676                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12677                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12678                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12679                 switch (layer->type)
12680                 {
12681                 case TEXTURELAYERTYPE_LITTEXTURE:
12682                         // single-pass lightmapped texture with 2x rgbscale
12683                         R_Mesh_TexBind(0, r_texture_white);
12684                         R_Mesh_TexMatrix(0, NULL);
12685                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12686                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12687                         R_Mesh_TexBind(1, layer->texture);
12688                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12689                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12690                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12691                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12692                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12693                         else if (FAKELIGHT_ENABLED)
12694                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12695                         else if (rsurface.uselightmaptexture)
12696                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12697                         else
12698                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12699                         break;
12700                 case TEXTURELAYERTYPE_TEXTURE:
12701                         // singletexture unlit texture with transparency support
12702                         R_Mesh_TexBind(0, layer->texture);
12703                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12704                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12705                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12706                         R_Mesh_TexBind(1, 0);
12707                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12708                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12709                         break;
12710                 case TEXTURELAYERTYPE_FOG:
12711                         // singletexture fogging
12712                         if (layer->texture)
12713                         {
12714                                 R_Mesh_TexBind(0, layer->texture);
12715                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12716                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12717                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12718                         }
12719                         else
12720                         {
12721                                 R_Mesh_TexBind(0, 0);
12722                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12723                         }
12724                         R_Mesh_TexBind(1, 0);
12725                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12726                         // generate a color array for the fog pass
12727                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12728                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12729                         RSurf_DrawBatch();
12730                         break;
12731                 default:
12732                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12733                 }
12734         }
12735         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12736         {
12737                 GL_DepthFunc(GL_LEQUAL);
12738                 GL_AlphaTest(false);
12739         }
12740 }
12741
12742 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12743 {
12744         // OpenGL 1.1 - crusty old voodoo path
12745         qboolean applyfog;
12746         int layerindex;
12747         const texturelayer_t *layer;
12748         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);
12749         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12750
12751         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12752         {
12753                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12754                 {
12755                         if (layerindex == 0)
12756                                 GL_AlphaTest(true);
12757                         else
12758                         {
12759                                 GL_AlphaTest(false);
12760                                 GL_DepthFunc(GL_EQUAL);
12761                         }
12762                 }
12763                 GL_DepthMask(layer->depthmask && writedepth);
12764                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12765                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12766                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12767                 switch (layer->type)
12768                 {
12769                 case TEXTURELAYERTYPE_LITTEXTURE:
12770                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12771                         {
12772                                 // two-pass lit texture with 2x rgbscale
12773                                 // first the lightmap pass
12774                                 R_Mesh_TexBind(0, r_texture_white);
12775                                 R_Mesh_TexMatrix(0, NULL);
12776                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12777                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12778                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12779                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12780                                 else if (FAKELIGHT_ENABLED)
12781                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12782                                 else if (rsurface.uselightmaptexture)
12783                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12784                                 else
12785                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12786                                 // then apply the texture to it
12787                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12788                                 R_Mesh_TexBind(0, layer->texture);
12789                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12790                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12791                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12792                                 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);
12793                         }
12794                         else
12795                         {
12796                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12797                                 R_Mesh_TexBind(0, layer->texture);
12798                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12799                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12800                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12801                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12802                                         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);
12803                                 else
12804                                         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);
12805                         }
12806                         break;
12807                 case TEXTURELAYERTYPE_TEXTURE:
12808                         // singletexture unlit texture with transparency support
12809                         R_Mesh_TexBind(0, layer->texture);
12810                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12811                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12812                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12813                         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);
12814                         break;
12815                 case TEXTURELAYERTYPE_FOG:
12816                         // singletexture fogging
12817                         if (layer->texture)
12818                         {
12819                                 R_Mesh_TexBind(0, layer->texture);
12820                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12821                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12822                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12823                         }
12824                         else
12825                         {
12826                                 R_Mesh_TexBind(0, 0);
12827                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12828                         }
12829                         // generate a color array for the fog pass
12830                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12831                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12832                         RSurf_DrawBatch();
12833                         break;
12834                 default:
12835                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12836                 }
12837         }
12838         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12839         {
12840                 GL_DepthFunc(GL_LEQUAL);
12841                 GL_AlphaTest(false);
12842         }
12843 }
12844
12845 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12846 {
12847         int vi;
12848         int j;
12849         r_vertexgeneric_t *batchvertex;
12850         float c[4];
12851
12852         GL_AlphaTest(false);
12853 //      R_Mesh_ResetTextureState();
12854         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12855
12856         if(rsurface.texture && rsurface.texture->currentskinframe)
12857         {
12858                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12859                 c[3] *= rsurface.texture->currentalpha;
12860         }
12861         else
12862         {
12863                 c[0] = 1;
12864                 c[1] = 0;
12865                 c[2] = 1;
12866                 c[3] = 1;
12867         }
12868
12869         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12870         {
12871                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12872                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12873                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12874         }
12875
12876         // brighten it up (as texture value 127 means "unlit")
12877         c[0] *= 2 * r_refdef.view.colorscale;
12878         c[1] *= 2 * r_refdef.view.colorscale;
12879         c[2] *= 2 * r_refdef.view.colorscale;
12880
12881         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12882                 c[3] *= r_wateralpha.value;
12883
12884         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12885         {
12886                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12887                 GL_DepthMask(false);
12888         }
12889         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12890         {
12891                 GL_BlendFunc(GL_ONE, GL_ONE);
12892                 GL_DepthMask(false);
12893         }
12894         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12895         {
12896                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12897                 GL_DepthMask(false);
12898         }
12899         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12900         {
12901                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12902                 GL_DepthMask(false);
12903         }
12904         else
12905         {
12906                 GL_BlendFunc(GL_ONE, GL_ZERO);
12907                 GL_DepthMask(writedepth);
12908         }
12909
12910         if (r_showsurfaces.integer == 3)
12911         {
12912                 rsurface.passcolor4f = NULL;
12913
12914                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12915                 {
12916                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12917
12918                         rsurface.passcolor4f = NULL;
12919                         rsurface.passcolor4f_vertexbuffer = 0;
12920                         rsurface.passcolor4f_bufferoffset = 0;
12921                 }
12922                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12923                 {
12924                         qboolean applycolor = true;
12925                         float one = 1.0;
12926
12927                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12928
12929                         r_refdef.lightmapintensity = 1;
12930                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12931                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12932                 }
12933                 else if (FAKELIGHT_ENABLED)
12934                 {
12935                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12936
12937                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12938                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12939                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12940                 }
12941                 else
12942                 {
12943                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12944
12945                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12946                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12947                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12948                 }
12949
12950                 if(!rsurface.passcolor4f)
12951                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12952
12953                 RSurf_DrawBatch_GL11_ApplyAmbient();
12954                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12955                 if(r_refdef.fogenabled)
12956                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12957                 RSurf_DrawBatch_GL11_ClampColor();
12958
12959                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12960                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12961                 RSurf_DrawBatch();
12962         }
12963         else if (!r_refdef.view.showdebug)
12964         {
12965                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12966                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12967                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12968                 {
12969                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12970                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12971                 }
12972                 R_Mesh_PrepareVertices_Generic_Unlock();
12973                 RSurf_DrawBatch();
12974         }
12975         else if (r_showsurfaces.integer == 4)
12976         {
12977                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12978                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12979                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12980                 {
12981                         unsigned char c = vi << 3;
12982                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12983                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12984                 }
12985                 R_Mesh_PrepareVertices_Generic_Unlock();
12986                 RSurf_DrawBatch();
12987         }
12988         else if (r_showsurfaces.integer == 2)
12989         {
12990                 const int *e;
12991                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12992                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12993                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12994                 {
12995                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12996                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12997                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12998                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12999                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13000                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13001                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13002                 }
13003                 R_Mesh_PrepareVertices_Generic_Unlock();
13004                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13005         }
13006         else
13007         {
13008                 int texturesurfaceindex;
13009                 int k;
13010                 const msurface_t *surface;
13011                 unsigned char surfacecolor4ub[4];
13012                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13013                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13014                 vi = 0;
13015                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13016                 {
13017                         surface = texturesurfacelist[texturesurfaceindex];
13018                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13019                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13020                         for (j = 0;j < surface->num_vertices;j++)
13021                         {
13022                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13023                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13024                                 vi++;
13025                         }
13026                 }
13027                 R_Mesh_PrepareVertices_Generic_Unlock();
13028                 RSurf_DrawBatch();
13029         }
13030 }
13031
13032 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13033 {
13034         CHECKGLERROR
13035         RSurf_SetupDepthAndCulling();
13036         if (r_showsurfaces.integer)
13037         {
13038                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13039                 return;
13040         }
13041         switch (vid.renderpath)
13042         {
13043         case RENDERPATH_GL20:
13044         case RENDERPATH_CGGL:
13045         case RENDERPATH_D3D9:
13046         case RENDERPATH_D3D10:
13047         case RENDERPATH_D3D11:
13048                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13049                 break;
13050         case RENDERPATH_GL13:
13051                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13052                 break;
13053         case RENDERPATH_GL11:
13054                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13055                 break;
13056         }
13057         CHECKGLERROR
13058 }
13059
13060 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13061 {
13062         CHECKGLERROR
13063         RSurf_SetupDepthAndCulling();
13064         if (r_showsurfaces.integer)
13065         {
13066                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13067                 return;
13068         }
13069         switch (vid.renderpath)
13070         {
13071         case RENDERPATH_GL20:
13072         case RENDERPATH_CGGL:
13073         case RENDERPATH_D3D9:
13074         case RENDERPATH_D3D10:
13075         case RENDERPATH_D3D11:
13076                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13077                 break;
13078         case RENDERPATH_GL13:
13079                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13080                 break;
13081         case RENDERPATH_GL11:
13082                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13083                 break;
13084         }
13085         CHECKGLERROR
13086 }
13087
13088 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13089 {
13090         int i, j;
13091         int texturenumsurfaces, endsurface;
13092         texture_t *texture;
13093         const msurface_t *surface;
13094 #define MAXBATCH_TRANSPARENTSURFACES 256
13095         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13096
13097         // if the model is static it doesn't matter what value we give for
13098         // wantnormals and wanttangents, so this logic uses only rules applicable
13099         // to a model, knowing that they are meaningless otherwise
13100         if (ent == r_refdef.scene.worldentity)
13101                 RSurf_ActiveWorldEntity();
13102         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13103                 RSurf_ActiveModelEntity(ent, false, false, false);
13104         else
13105         {
13106                 switch (vid.renderpath)
13107                 {
13108                 case RENDERPATH_GL20:
13109                 case RENDERPATH_CGGL:
13110                 case RENDERPATH_D3D9:
13111                 case RENDERPATH_D3D10:
13112                 case RENDERPATH_D3D11:
13113                         RSurf_ActiveModelEntity(ent, true, true, false);
13114                         break;
13115                 case RENDERPATH_GL13:
13116                 case RENDERPATH_GL11:
13117                         RSurf_ActiveModelEntity(ent, true, false, false);
13118                         break;
13119                 }
13120         }
13121
13122         if (r_transparentdepthmasking.integer)
13123         {
13124                 qboolean setup = false;
13125                 for (i = 0;i < numsurfaces;i = j)
13126                 {
13127                         j = i + 1;
13128                         surface = rsurface.modelsurfaces + surfacelist[i];
13129                         texture = surface->texture;
13130                         rsurface.texture = R_GetCurrentTexture(texture);
13131                         rsurface.lightmaptexture = NULL;
13132                         rsurface.deluxemaptexture = NULL;
13133                         rsurface.uselightmaptexture = false;
13134                         // scan ahead until we find a different texture
13135                         endsurface = min(i + 1024, numsurfaces);
13136                         texturenumsurfaces = 0;
13137                         texturesurfacelist[texturenumsurfaces++] = surface;
13138                         for (;j < endsurface;j++)
13139                         {
13140                                 surface = rsurface.modelsurfaces + surfacelist[j];
13141                                 if (texture != surface->texture)
13142                                         break;
13143                                 texturesurfacelist[texturenumsurfaces++] = surface;
13144                         }
13145                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13146                                 continue;
13147                         // render the range of surfaces as depth
13148                         if (!setup)
13149                         {
13150                                 setup = true;
13151                                 GL_ColorMask(0,0,0,0);
13152                                 GL_Color(1,1,1,1);
13153                                 GL_DepthTest(true);
13154                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13155                                 GL_DepthMask(true);
13156                                 GL_AlphaTest(false);
13157 //                              R_Mesh_ResetTextureState();
13158                                 R_SetupShader_DepthOrShadow();
13159                         }
13160                         RSurf_SetupDepthAndCulling();
13161                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13162                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13163                         RSurf_DrawBatch();
13164                 }
13165                 if (setup)
13166                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13167         }
13168
13169         for (i = 0;i < numsurfaces;i = j)
13170         {
13171                 j = i + 1;
13172                 surface = rsurface.modelsurfaces + surfacelist[i];
13173                 texture = surface->texture;
13174                 rsurface.texture = R_GetCurrentTexture(texture);
13175                 // scan ahead until we find a different texture
13176                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13177                 texturenumsurfaces = 0;
13178                 texturesurfacelist[texturenumsurfaces++] = surface;
13179                 if(FAKELIGHT_ENABLED)
13180                 {
13181                         rsurface.lightmaptexture = NULL;
13182                         rsurface.deluxemaptexture = NULL;
13183                         rsurface.uselightmaptexture = false;
13184                         for (;j < endsurface;j++)
13185                         {
13186                                 surface = rsurface.modelsurfaces + surfacelist[j];
13187                                 if (texture != surface->texture)
13188                                         break;
13189                                 texturesurfacelist[texturenumsurfaces++] = surface;
13190                         }
13191                 }
13192                 else
13193                 {
13194                         rsurface.lightmaptexture = surface->lightmaptexture;
13195                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13196                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13197                         for (;j < endsurface;j++)
13198                         {
13199                                 surface = rsurface.modelsurfaces + surfacelist[j];
13200                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13201                                         break;
13202                                 texturesurfacelist[texturenumsurfaces++] = surface;
13203                         }
13204                 }
13205                 // render the range of surfaces
13206                 if (ent == r_refdef.scene.worldentity)
13207                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13208                 else
13209                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13210         }
13211         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13212         GL_AlphaTest(false);
13213 }
13214
13215 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13216 {
13217         // transparent surfaces get pushed off into the transparent queue
13218         int surfacelistindex;
13219         const msurface_t *surface;
13220         vec3_t tempcenter, center;
13221         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13222         {
13223                 surface = texturesurfacelist[surfacelistindex];
13224                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13225                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13226                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13227                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13228                 if (queueentity->transparent_offset) // transparent offset
13229                 {
13230                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13231                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13232                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13233                 }
13234                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13235         }
13236 }
13237
13238 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13239 {
13240         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13241                 return;
13242         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13243                 return;
13244         RSurf_SetupDepthAndCulling();
13245         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13246         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13247         RSurf_DrawBatch();
13248 }
13249
13250 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13251 {
13252         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13253         CHECKGLERROR
13254         if (depthonly)
13255                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13256         else if (prepass)
13257         {
13258                 if (!rsurface.texture->currentnumlayers)
13259                         return;
13260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13261                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13262                 else
13263                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13264         }
13265         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13266                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13267         else if (!rsurface.texture->currentnumlayers)
13268                 return;
13269         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13270         {
13271                 // in the deferred case, transparent surfaces were queued during prepass
13272                 if (!r_shadow_usingdeferredprepass)
13273                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13274         }
13275         else
13276         {
13277                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13278                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13279         }
13280         CHECKGLERROR
13281 }
13282
13283 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13284 {
13285         int i, j;
13286         texture_t *texture;
13287         // break the surface list down into batches by texture and use of lightmapping
13288         for (i = 0;i < numsurfaces;i = j)
13289         {
13290                 j = i + 1;
13291                 // texture is the base texture pointer, rsurface.texture is the
13292                 // current frame/skin the texture is directing us to use (for example
13293                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13294                 // use skin 1 instead)
13295                 texture = surfacelist[i]->texture;
13296                 rsurface.texture = R_GetCurrentTexture(texture);
13297                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13298                 {
13299                         // if this texture is not the kind we want, skip ahead to the next one
13300                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13301                                 ;
13302                         continue;
13303                 }
13304                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13305                 {
13306                         rsurface.lightmaptexture = NULL;
13307                         rsurface.deluxemaptexture = NULL;
13308                         rsurface.uselightmaptexture = false;
13309                         // simply scan ahead until we find a different texture or lightmap state
13310                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13311                                 ;
13312                 }
13313                 else
13314                 {
13315                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13316                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13317                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13318                         // simply scan ahead until we find a different texture or lightmap state
13319                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13320                                 ;
13321                 }
13322                 // render the range of surfaces
13323                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13324         }
13325 }
13326
13327 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13328 {
13329         CHECKGLERROR
13330         if (depthonly)
13331                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13332         else if (prepass)
13333         {
13334                 if (!rsurface.texture->currentnumlayers)
13335                         return;
13336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13337                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13338                 else
13339                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13340         }
13341         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13342                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13343         else if (!rsurface.texture->currentnumlayers)
13344                 return;
13345         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13346         {
13347                 // in the deferred case, transparent surfaces were queued during prepass
13348                 if (!r_shadow_usingdeferredprepass)
13349                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13350         }
13351         else
13352         {
13353                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13354                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13355         }
13356         CHECKGLERROR
13357 }
13358
13359 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13360 {
13361         int i, j;
13362         texture_t *texture;
13363         // break the surface list down into batches by texture and use of lightmapping
13364         for (i = 0;i < numsurfaces;i = j)
13365         {
13366                 j = i + 1;
13367                 // texture is the base texture pointer, rsurface.texture is the
13368                 // current frame/skin the texture is directing us to use (for example
13369                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13370                 // use skin 1 instead)
13371                 texture = surfacelist[i]->texture;
13372                 rsurface.texture = R_GetCurrentTexture(texture);
13373                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13374                 {
13375                         // if this texture is not the kind we want, skip ahead to the next one
13376                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13377                                 ;
13378                         continue;
13379                 }
13380                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13381                 {
13382                         rsurface.lightmaptexture = NULL;
13383                         rsurface.deluxemaptexture = NULL;
13384                         rsurface.uselightmaptexture = false;
13385                         // simply scan ahead until we find a different texture or lightmap state
13386                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13387                                 ;
13388                 }
13389                 else
13390                 {
13391                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13392                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13393                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13394                         // simply scan ahead until we find a different texture or lightmap state
13395                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13396                                 ;
13397                 }
13398                 // render the range of surfaces
13399                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13400         }
13401 }
13402
13403 float locboxvertex3f[6*4*3] =
13404 {
13405         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13406         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13407         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13408         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13409         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13410         1,0,0, 0,0,0, 0,1,0, 1,1,0
13411 };
13412
13413 unsigned short locboxelements[6*2*3] =
13414 {
13415          0, 1, 2, 0, 2, 3,
13416          4, 5, 6, 4, 6, 7,
13417          8, 9,10, 8,10,11,
13418         12,13,14, 12,14,15,
13419         16,17,18, 16,18,19,
13420         20,21,22, 20,22,23
13421 };
13422
13423 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13424 {
13425         int i, j;
13426         cl_locnode_t *loc = (cl_locnode_t *)ent;
13427         vec3_t mins, size;
13428         float vertex3f[6*4*3];
13429         CHECKGLERROR
13430         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13431         GL_DepthMask(false);
13432         GL_DepthRange(0, 1);
13433         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13434         GL_DepthTest(true);
13435         GL_CullFace(GL_NONE);
13436         R_EntityMatrix(&identitymatrix);
13437
13438 //      R_Mesh_ResetTextureState();
13439
13440         i = surfacelist[0];
13441         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13442                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13443                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13444                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13445
13446         if (VectorCompare(loc->mins, loc->maxs))
13447         {
13448                 VectorSet(size, 2, 2, 2);
13449                 VectorMA(loc->mins, -0.5f, size, mins);
13450         }
13451         else
13452         {
13453                 VectorCopy(loc->mins, mins);
13454                 VectorSubtract(loc->maxs, loc->mins, size);
13455         }
13456
13457         for (i = 0;i < 6*4*3;)
13458                 for (j = 0;j < 3;j++, i++)
13459                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13460
13461         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13462         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13463         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13464 }
13465
13466 void R_DrawLocs(void)
13467 {
13468         int index;
13469         cl_locnode_t *loc, *nearestloc;
13470         vec3_t center;
13471         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13472         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13473         {
13474                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13475                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13476         }
13477 }
13478
13479 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13480 {
13481         if (decalsystem->decals)
13482                 Mem_Free(decalsystem->decals);
13483         memset(decalsystem, 0, sizeof(*decalsystem));
13484 }
13485
13486 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)
13487 {
13488         tridecal_t *decal;
13489         tridecal_t *decals;
13490         int i;
13491
13492         // expand or initialize the system
13493         if (decalsystem->maxdecals <= decalsystem->numdecals)
13494         {
13495                 decalsystem_t old = *decalsystem;
13496                 qboolean useshortelements;
13497                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13498                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13499                 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)));
13500                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13501                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13502                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13503                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13504                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13505                 if (decalsystem->numdecals)
13506                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13507                 if (old.decals)
13508                         Mem_Free(old.decals);
13509                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13510                         decalsystem->element3i[i] = i;
13511                 if (useshortelements)
13512                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13513                                 decalsystem->element3s[i] = i;
13514         }
13515
13516         // grab a decal and search for another free slot for the next one
13517         decals = decalsystem->decals;
13518         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13519         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13520                 ;
13521         decalsystem->freedecal = i;
13522         if (decalsystem->numdecals <= i)
13523                 decalsystem->numdecals = i + 1;
13524
13525         // initialize the decal
13526         decal->lived = 0;
13527         decal->triangleindex = triangleindex;
13528         decal->surfaceindex = surfaceindex;
13529         decal->decalsequence = decalsequence;
13530         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13531         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13532         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13533         decal->color4ub[0][3] = 255;
13534         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13535         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13536         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13537         decal->color4ub[1][3] = 255;
13538         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13539         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13540         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13541         decal->color4ub[2][3] = 255;
13542         decal->vertex3f[0][0] = v0[0];
13543         decal->vertex3f[0][1] = v0[1];
13544         decal->vertex3f[0][2] = v0[2];
13545         decal->vertex3f[1][0] = v1[0];
13546         decal->vertex3f[1][1] = v1[1];
13547         decal->vertex3f[1][2] = v1[2];
13548         decal->vertex3f[2][0] = v2[0];
13549         decal->vertex3f[2][1] = v2[1];
13550         decal->vertex3f[2][2] = v2[2];
13551         decal->texcoord2f[0][0] = t0[0];
13552         decal->texcoord2f[0][1] = t0[1];
13553         decal->texcoord2f[1][0] = t1[0];
13554         decal->texcoord2f[1][1] = t1[1];
13555         decal->texcoord2f[2][0] = t2[0];
13556         decal->texcoord2f[2][1] = t2[1];
13557 }
13558
13559 extern cvar_t cl_decals_bias;
13560 extern cvar_t cl_decals_models;
13561 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13562 // baseparms, parms, temps
13563 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)
13564 {
13565         int cornerindex;
13566         int index;
13567         float v[9][3];
13568         const float *vertex3f;
13569         int numpoints;
13570         float points[2][9][3];
13571         float temp[3];
13572         float tc[9][2];
13573         float f;
13574         float c[9][4];
13575         const int *e;
13576
13577         e = rsurface.modelelement3i + 3*triangleindex;
13578
13579         vertex3f = rsurface.modelvertex3f;
13580
13581         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13582         {
13583                 index = 3*e[cornerindex];
13584                 VectorCopy(vertex3f + index, v[cornerindex]);
13585         }
13586         // cull backfaces
13587         //TriangleNormal(v[0], v[1], v[2], normal);
13588         //if (DotProduct(normal, localnormal) < 0.0f)
13589         //      continue;
13590         // clip by each of the box planes formed from the projection matrix
13591         // if anything survives, we emit the decal
13592         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]);
13593         if (numpoints < 3)
13594                 return;
13595         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]);
13596         if (numpoints < 3)
13597                 return;
13598         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]);
13599         if (numpoints < 3)
13600                 return;
13601         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]);
13602         if (numpoints < 3)
13603                 return;
13604         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]);
13605         if (numpoints < 3)
13606                 return;
13607         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]);
13608         if (numpoints < 3)
13609                 return;
13610         // some part of the triangle survived, so we have to accept it...
13611         if (dynamic)
13612         {
13613                 // dynamic always uses the original triangle
13614                 numpoints = 3;
13615                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13616                 {
13617                         index = 3*e[cornerindex];
13618                         VectorCopy(vertex3f + index, v[cornerindex]);
13619                 }
13620         }
13621         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13622         {
13623                 // convert vertex positions to texcoords
13624                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13625                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13626                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13627                 // calculate distance fade from the projection origin
13628                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13629                 f = bound(0.0f, f, 1.0f);
13630                 c[cornerindex][0] = r * f;
13631                 c[cornerindex][1] = g * f;
13632                 c[cornerindex][2] = b * f;
13633                 c[cornerindex][3] = 1.0f;
13634                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13635         }
13636         if (dynamic)
13637                 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);
13638         else
13639                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13640                         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);
13641 }
13642 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)
13643 {
13644         matrix4x4_t projection;
13645         decalsystem_t *decalsystem;
13646         qboolean dynamic;
13647         dp_model_t *model;
13648         const msurface_t *surface;
13649         const msurface_t *surfaces;
13650         const int *surfacelist;
13651         const texture_t *texture;
13652         int numtriangles;
13653         int numsurfacelist;
13654         int surfacelistindex;
13655         int surfaceindex;
13656         int triangleindex;
13657         float localorigin[3];
13658         float localnormal[3];
13659         float localmins[3];
13660         float localmaxs[3];
13661         float localsize;
13662         //float normal[3];
13663         float planes[6][4];
13664         float angles[3];
13665         bih_t *bih;
13666         int bih_triangles_count;
13667         int bih_triangles[256];
13668         int bih_surfaces[256];
13669
13670         decalsystem = &ent->decalsystem;
13671         model = ent->model;
13672         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13673         {
13674                 R_DecalSystem_Reset(&ent->decalsystem);
13675                 return;
13676         }
13677
13678         if (!model->brush.data_leafs && !cl_decals_models.integer)
13679         {
13680                 if (decalsystem->model)
13681                         R_DecalSystem_Reset(decalsystem);
13682                 return;
13683         }
13684
13685         if (decalsystem->model != model)
13686                 R_DecalSystem_Reset(decalsystem);
13687         decalsystem->model = model;
13688
13689         RSurf_ActiveModelEntity(ent, false, false, false);
13690
13691         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13692         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13693         VectorNormalize(localnormal);
13694         localsize = worldsize*rsurface.inversematrixscale;
13695         localmins[0] = localorigin[0] - localsize;
13696         localmins[1] = localorigin[1] - localsize;
13697         localmins[2] = localorigin[2] - localsize;
13698         localmaxs[0] = localorigin[0] + localsize;
13699         localmaxs[1] = localorigin[1] + localsize;
13700         localmaxs[2] = localorigin[2] + localsize;
13701
13702         //VectorCopy(localnormal, planes[4]);
13703         //VectorVectors(planes[4], planes[2], planes[0]);
13704         AnglesFromVectors(angles, localnormal, NULL, false);
13705         AngleVectors(angles, planes[0], planes[2], planes[4]);
13706         VectorNegate(planes[0], planes[1]);
13707         VectorNegate(planes[2], planes[3]);
13708         VectorNegate(planes[4], planes[5]);
13709         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13710         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13711         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13712         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13713         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13714         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13715
13716 #if 1
13717 // works
13718 {
13719         matrix4x4_t forwardprojection;
13720         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13721         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13722 }
13723 #else
13724 // broken
13725 {
13726         float projectionvector[4][3];
13727         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13728         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13729         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13730         projectionvector[0][0] = planes[0][0] * ilocalsize;
13731         projectionvector[0][1] = planes[1][0] * ilocalsize;
13732         projectionvector[0][2] = planes[2][0] * ilocalsize;
13733         projectionvector[1][0] = planes[0][1] * ilocalsize;
13734         projectionvector[1][1] = planes[1][1] * ilocalsize;
13735         projectionvector[1][2] = planes[2][1] * ilocalsize;
13736         projectionvector[2][0] = planes[0][2] * ilocalsize;
13737         projectionvector[2][1] = planes[1][2] * ilocalsize;
13738         projectionvector[2][2] = planes[2][2] * ilocalsize;
13739         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13740         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13741         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13742         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13743 }
13744 #endif
13745
13746         dynamic = model->surfmesh.isanimated;
13747         numsurfacelist = model->nummodelsurfaces;
13748         surfacelist = model->sortedmodelsurfaces;
13749         surfaces = model->data_surfaces;
13750
13751         bih = NULL;
13752         bih_triangles_count = -1;
13753         if(!dynamic)
13754         {
13755                 if(model->render_bih.numleafs)
13756                         bih = &model->render_bih;
13757                 else if(model->collision_bih.numleafs)
13758                         bih = &model->collision_bih;
13759         }
13760         if(bih)
13761                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13762         if(bih_triangles_count == 0)
13763                 return;
13764         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13765                 return;
13766         if(bih_triangles_count > 0)
13767         {
13768                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13769                 {
13770                         surfaceindex = bih_surfaces[triangleindex];
13771                         surface = surfaces + surfaceindex;
13772                         texture = surface->texture;
13773                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13774                                 continue;
13775                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13776                                 continue;
13777                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13778                 }
13779         }
13780         else
13781         {
13782                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13783                 {
13784                         surfaceindex = surfacelist[surfacelistindex];
13785                         surface = surfaces + surfaceindex;
13786                         // check cull box first because it rejects more than any other check
13787                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13788                                 continue;
13789                         // skip transparent surfaces
13790                         texture = surface->texture;
13791                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13792                                 continue;
13793                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13794                                 continue;
13795                         numtriangles = surface->num_triangles;
13796                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13797                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13798                 }
13799         }
13800 }
13801
13802 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13803 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)
13804 {
13805         int renderentityindex;
13806         float worldmins[3];
13807         float worldmaxs[3];
13808         entity_render_t *ent;
13809
13810         if (!cl_decals_newsystem.integer)
13811                 return;
13812
13813         worldmins[0] = worldorigin[0] - worldsize;
13814         worldmins[1] = worldorigin[1] - worldsize;
13815         worldmins[2] = worldorigin[2] - worldsize;
13816         worldmaxs[0] = worldorigin[0] + worldsize;
13817         worldmaxs[1] = worldorigin[1] + worldsize;
13818         worldmaxs[2] = worldorigin[2] + worldsize;
13819
13820         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13821
13822         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13823         {
13824                 ent = r_refdef.scene.entities[renderentityindex];
13825                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13826                         continue;
13827
13828                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13829         }
13830 }
13831
13832 typedef struct r_decalsystem_splatqueue_s
13833 {
13834         vec3_t worldorigin;
13835         vec3_t worldnormal;
13836         float color[4];
13837         float tcrange[4];
13838         float worldsize;
13839         int decalsequence;
13840 }
13841 r_decalsystem_splatqueue_t;
13842
13843 int r_decalsystem_numqueued = 0;
13844 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13845
13846 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)
13847 {
13848         r_decalsystem_splatqueue_t *queue;
13849
13850         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13851                 return;
13852
13853         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13854         VectorCopy(worldorigin, queue->worldorigin);
13855         VectorCopy(worldnormal, queue->worldnormal);
13856         Vector4Set(queue->color, r, g, b, a);
13857         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13858         queue->worldsize = worldsize;
13859         queue->decalsequence = cl.decalsequence++;
13860 }
13861
13862 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13863 {
13864         int i;
13865         r_decalsystem_splatqueue_t *queue;
13866
13867         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13868                 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);
13869         r_decalsystem_numqueued = 0;
13870 }
13871
13872 extern cvar_t cl_decals_max;
13873 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13874 {
13875         int i;
13876         decalsystem_t *decalsystem = &ent->decalsystem;
13877         int numdecals;
13878         int killsequence;
13879         tridecal_t *decal;
13880         float frametime;
13881         float lifetime;
13882
13883         if (!decalsystem->numdecals)
13884                 return;
13885
13886         if (r_showsurfaces.integer)
13887                 return;
13888
13889         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13890         {
13891                 R_DecalSystem_Reset(decalsystem);
13892                 return;
13893         }
13894
13895         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13896         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13897
13898         if (decalsystem->lastupdatetime)
13899                 frametime = (cl.time - decalsystem->lastupdatetime);
13900         else
13901                 frametime = 0;
13902         decalsystem->lastupdatetime = cl.time;
13903         decal = decalsystem->decals;
13904         numdecals = decalsystem->numdecals;
13905
13906         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13907         {
13908                 if (decal->color4ub[0][3])
13909                 {
13910                         decal->lived += frametime;
13911                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13912                         {
13913                                 memset(decal, 0, sizeof(*decal));
13914                                 if (decalsystem->freedecal > i)
13915                                         decalsystem->freedecal = i;
13916                         }
13917                 }
13918         }
13919         decal = decalsystem->decals;
13920         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13921                 numdecals--;
13922
13923         // collapse the array by shuffling the tail decals into the gaps
13924         for (;;)
13925         {
13926                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13927                         decalsystem->freedecal++;
13928                 if (decalsystem->freedecal == numdecals)
13929                         break;
13930                 decal[decalsystem->freedecal] = decal[--numdecals];
13931         }
13932
13933         decalsystem->numdecals = numdecals;
13934
13935         if (numdecals <= 0)
13936         {
13937                 // if there are no decals left, reset decalsystem
13938                 R_DecalSystem_Reset(decalsystem);
13939         }
13940 }
13941
13942 extern skinframe_t *decalskinframe;
13943 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13944 {
13945         int i;
13946         decalsystem_t *decalsystem = &ent->decalsystem;
13947         int numdecals;
13948         tridecal_t *decal;
13949         float faderate;
13950         float alpha;
13951         float *v3f;
13952         float *c4f;
13953         float *t2f;
13954         const int *e;
13955         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13956         int numtris = 0;
13957
13958         numdecals = decalsystem->numdecals;
13959         if (!numdecals)
13960                 return;
13961
13962         if (r_showsurfaces.integer)
13963                 return;
13964
13965         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13966         {
13967                 R_DecalSystem_Reset(decalsystem);
13968                 return;
13969         }
13970
13971         // if the model is static it doesn't matter what value we give for
13972         // wantnormals and wanttangents, so this logic uses only rules applicable
13973         // to a model, knowing that they are meaningless otherwise
13974         if (ent == r_refdef.scene.worldentity)
13975                 RSurf_ActiveWorldEntity();
13976         else
13977                 RSurf_ActiveModelEntity(ent, false, false, false);
13978
13979         decalsystem->lastupdatetime = cl.time;
13980         decal = decalsystem->decals;
13981
13982         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13983
13984         // update vertex positions for animated models
13985         v3f = decalsystem->vertex3f;
13986         c4f = decalsystem->color4f;
13987         t2f = decalsystem->texcoord2f;
13988         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13989         {
13990                 if (!decal->color4ub[0][3])
13991                         continue;
13992
13993                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13994                         continue;
13995
13996                 // update color values for fading decals
13997                 if (decal->lived >= cl_decals_time.value)
13998                 {
13999                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14000                         alpha *= (1.0f/255.0f);
14001                 }
14002                 else
14003                         alpha = 1.0f/255.0f;
14004
14005                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14006                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14007                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14008                 c4f[ 3] = 1;
14009                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14010                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14011                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14012                 c4f[ 7] = 1;
14013                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14014                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14015                 c4f[10] = decal->color4ub[2][2] * alpha;
14016                 c4f[11] = 1;
14017
14018                 t2f[0] = decal->texcoord2f[0][0];
14019                 t2f[1] = decal->texcoord2f[0][1];
14020                 t2f[2] = decal->texcoord2f[1][0];
14021                 t2f[3] = decal->texcoord2f[1][1];
14022                 t2f[4] = decal->texcoord2f[2][0];
14023                 t2f[5] = decal->texcoord2f[2][1];
14024
14025                 // update vertex positions for animated models
14026                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14027                 {
14028                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14029                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14030                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14031                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14032                 }
14033                 else
14034                 {
14035                         VectorCopy(decal->vertex3f[0], v3f);
14036                         VectorCopy(decal->vertex3f[1], v3f + 3);
14037                         VectorCopy(decal->vertex3f[2], v3f + 6);
14038                 }
14039
14040                 if (r_refdef.fogenabled)
14041                 {
14042                         alpha = RSurf_FogVertex(v3f);
14043                         VectorScale(c4f, alpha, c4f);
14044                         alpha = RSurf_FogVertex(v3f + 3);
14045                         VectorScale(c4f + 4, alpha, c4f + 4);
14046                         alpha = RSurf_FogVertex(v3f + 6);
14047                         VectorScale(c4f + 8, alpha, c4f + 8);
14048                 }
14049
14050                 v3f += 9;
14051                 c4f += 12;
14052                 t2f += 6;
14053                 numtris++;
14054         }
14055
14056         if (numtris > 0)
14057         {
14058                 r_refdef.stats.drawndecals += numtris;
14059
14060                 // now render the decals all at once
14061                 // (this assumes they all use one particle font texture!)
14062                 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);
14063 //              R_Mesh_ResetTextureState();
14064                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14065                 GL_DepthMask(false);
14066                 GL_DepthRange(0, 1);
14067                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14068                 GL_DepthTest(true);
14069                 GL_CullFace(GL_NONE);
14070                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14071                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14072                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14073         }
14074 }
14075
14076 static void R_DrawModelDecals(void)
14077 {
14078         int i, numdecals;
14079
14080         // fade faster when there are too many decals
14081         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14082         for (i = 0;i < r_refdef.scene.numentities;i++)
14083                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14084
14085         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14086         for (i = 0;i < r_refdef.scene.numentities;i++)
14087                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14088                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14089
14090         R_DecalSystem_ApplySplatEntitiesQueue();
14091
14092         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14093         for (i = 0;i < r_refdef.scene.numentities;i++)
14094                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14095
14096         r_refdef.stats.totaldecals += numdecals;
14097
14098         if (r_showsurfaces.integer)
14099                 return;
14100
14101         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14102
14103         for (i = 0;i < r_refdef.scene.numentities;i++)
14104         {
14105                 if (!r_refdef.viewcache.entityvisible[i])
14106                         continue;
14107                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14108                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14109         }
14110 }
14111
14112 extern cvar_t mod_collision_bih;
14113 void R_DrawDebugModel(void)
14114 {
14115         entity_render_t *ent = rsurface.entity;
14116         int i, j, k, l, flagsmask;
14117         const msurface_t *surface;
14118         dp_model_t *model = ent->model;
14119         vec3_t v;
14120
14121         switch(vid.renderpath)
14122         {
14123         case RENDERPATH_GL11:
14124         case RENDERPATH_GL13:
14125         case RENDERPATH_GL20:
14126         case RENDERPATH_CGGL:
14127                 break;
14128         case RENDERPATH_D3D9:
14129                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14130                 return;
14131         case RENDERPATH_D3D10:
14132                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14133                 return;
14134         case RENDERPATH_D3D11:
14135                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14136                 return;
14137         }
14138
14139         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14140
14141 //      R_Mesh_ResetTextureState();
14142         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14143         GL_DepthRange(0, 1);
14144         GL_DepthTest(!r_showdisabledepthtest.integer);
14145         GL_DepthMask(false);
14146         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14147
14148         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14149         {
14150                 int triangleindex;
14151                 int bihleafindex;
14152                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14153                 const q3mbrush_t *brush;
14154                 const bih_t *bih = &model->collision_bih;
14155                 const bih_leaf_t *bihleaf;
14156                 float vertex3f[3][3];
14157                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14158                 cullbox = false;
14159                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14160                 {
14161                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14162                                 continue;
14163                         switch (bihleaf->type)
14164                         {
14165                         case BIH_BRUSH:
14166                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14167                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14168                                 {
14169                                         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);
14170                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14171                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14172                                 }
14173                                 break;
14174                         case BIH_COLLISIONTRIANGLE:
14175                                 triangleindex = bihleaf->itemindex;
14176                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14177                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14178                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14179                                 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);
14180                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14181                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14182                                 break;
14183                         case BIH_RENDERTRIANGLE:
14184                                 triangleindex = bihleaf->itemindex;
14185                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14186                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14187                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14188                                 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);
14189                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14190                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14191                                 break;
14192                         }
14193                 }
14194         }
14195
14196         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14197
14198         if (r_showtris.integer || r_shownormals.integer)
14199         {
14200                 if (r_showdisabledepthtest.integer)
14201                 {
14202                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14203                         GL_DepthMask(false);
14204                 }
14205                 else
14206                 {
14207                         GL_BlendFunc(GL_ONE, GL_ZERO);
14208                         GL_DepthMask(true);
14209                 }
14210                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14211                 {
14212                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14213                                 continue;
14214                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14215                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14216                         {
14217                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14218                                 if (r_showtris.value > 0)
14219                                 {
14220                                         if (!rsurface.texture->currentlayers->depthmask)
14221                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14222                                         else if (ent == r_refdef.scene.worldentity)
14223                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14224                                         else
14225                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14226                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14227                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14228                                         RSurf_DrawBatch();
14229                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14230                                         CHECKGLERROR
14231                                 }
14232                                 if (r_shownormals.value < 0)
14233                                 {
14234                                         qglBegin(GL_LINES);
14235                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14236                                         {
14237                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14238                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14239                                                 qglVertex3f(v[0], v[1], v[2]);
14240                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14241                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14242                                                 qglVertex3f(v[0], v[1], v[2]);
14243                                         }
14244                                         qglEnd();
14245                                         CHECKGLERROR
14246                                 }
14247                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14248                                 {
14249                                         qglBegin(GL_LINES);
14250                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14251                                         {
14252                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14253                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14254                                                 qglVertex3f(v[0], v[1], v[2]);
14255                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14256                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14257                                                 qglVertex3f(v[0], v[1], v[2]);
14258                                         }
14259                                         qglEnd();
14260                                         CHECKGLERROR
14261                                         qglBegin(GL_LINES);
14262                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14263                                         {
14264                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14265                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14266                                                 qglVertex3f(v[0], v[1], v[2]);
14267                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14268                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14269                                                 qglVertex3f(v[0], v[1], v[2]);
14270                                         }
14271                                         qglEnd();
14272                                         CHECKGLERROR
14273                                         qglBegin(GL_LINES);
14274                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14275                                         {
14276                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14277                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14278                                                 qglVertex3f(v[0], v[1], v[2]);
14279                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14280                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14281                                                 qglVertex3f(v[0], v[1], v[2]);
14282                                         }
14283                                         qglEnd();
14284                                         CHECKGLERROR
14285                                 }
14286                         }
14287                 }
14288                 rsurface.texture = NULL;
14289         }
14290 }
14291
14292 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14293 int r_maxsurfacelist = 0;
14294 const msurface_t **r_surfacelist = NULL;
14295 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14296 {
14297         int i, j, endj, flagsmask;
14298         dp_model_t *model = r_refdef.scene.worldmodel;
14299         msurface_t *surfaces;
14300         unsigned char *update;
14301         int numsurfacelist = 0;
14302         if (model == NULL)
14303                 return;
14304
14305         if (r_maxsurfacelist < model->num_surfaces)
14306         {
14307                 r_maxsurfacelist = model->num_surfaces;
14308                 if (r_surfacelist)
14309                         Mem_Free((msurface_t**)r_surfacelist);
14310                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14311         }
14312
14313         RSurf_ActiveWorldEntity();
14314
14315         surfaces = model->data_surfaces;
14316         update = model->brushq1.lightmapupdateflags;
14317
14318         // update light styles on this submodel
14319         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14320         {
14321                 model_brush_lightstyleinfo_t *style;
14322                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14323                 {
14324                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14325                         {
14326                                 int *list = style->surfacelist;
14327                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14328                                 for (j = 0;j < style->numsurfaces;j++)
14329                                         update[list[j]] = true;
14330                         }
14331                 }
14332         }
14333
14334         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14335
14336         if (debug)
14337         {
14338                 R_DrawDebugModel();
14339                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14340                 return;
14341         }
14342
14343         rsurface.lightmaptexture = NULL;
14344         rsurface.deluxemaptexture = NULL;
14345         rsurface.uselightmaptexture = false;
14346         rsurface.texture = NULL;
14347         rsurface.rtlight = NULL;
14348         numsurfacelist = 0;
14349         // add visible surfaces to draw list
14350         for (i = 0;i < model->nummodelsurfaces;i++)
14351         {
14352                 j = model->sortedmodelsurfaces[i];
14353                 if (r_refdef.viewcache.world_surfacevisible[j])
14354                         r_surfacelist[numsurfacelist++] = surfaces + j;
14355         }
14356         // update lightmaps if needed
14357         if (model->brushq1.firstrender)
14358         {
14359                 model->brushq1.firstrender = false;
14360                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14361                         if (update[j])
14362                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14363         }
14364         else if (update)
14365         {
14366                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14367                         if (r_refdef.viewcache.world_surfacevisible[j])
14368                                 if (update[j])
14369                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14370         }
14371         // don't do anything if there were no surfaces
14372         if (!numsurfacelist)
14373         {
14374                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14375                 return;
14376         }
14377         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14378         GL_AlphaTest(false);
14379
14380         // add to stats if desired
14381         if (r_speeds.integer && !skysurfaces && !depthonly)
14382         {
14383                 r_refdef.stats.world_surfaces += numsurfacelist;
14384                 for (j = 0;j < numsurfacelist;j++)
14385                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14386         }
14387
14388         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14389 }
14390
14391 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14392 {
14393         int i, j, endj, flagsmask;
14394         dp_model_t *model = ent->model;
14395         msurface_t *surfaces;
14396         unsigned char *update;
14397         int numsurfacelist = 0;
14398         if (model == NULL)
14399                 return;
14400
14401         if (r_maxsurfacelist < model->num_surfaces)
14402         {
14403                 r_maxsurfacelist = model->num_surfaces;
14404                 if (r_surfacelist)
14405                         Mem_Free((msurface_t **)r_surfacelist);
14406                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14407         }
14408
14409         // if the model is static it doesn't matter what value we give for
14410         // wantnormals and wanttangents, so this logic uses only rules applicable
14411         // to a model, knowing that they are meaningless otherwise
14412         if (ent == r_refdef.scene.worldentity)
14413                 RSurf_ActiveWorldEntity();
14414         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14415                 RSurf_ActiveModelEntity(ent, false, false, false);
14416         else if (prepass)
14417                 RSurf_ActiveModelEntity(ent, true, true, true);
14418         else if (depthonly)
14419         {
14420                 switch (vid.renderpath)
14421                 {
14422                 case RENDERPATH_GL20:
14423                 case RENDERPATH_CGGL:
14424                 case RENDERPATH_D3D9:
14425                 case RENDERPATH_D3D10:
14426                 case RENDERPATH_D3D11:
14427                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14428                         break;
14429                 case RENDERPATH_GL13:
14430                 case RENDERPATH_GL11:
14431                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14432                         break;
14433                 }
14434         }
14435         else
14436         {
14437                 switch (vid.renderpath)
14438                 {
14439                 case RENDERPATH_GL20:
14440                 case RENDERPATH_CGGL:
14441                 case RENDERPATH_D3D9:
14442                 case RENDERPATH_D3D10:
14443                 case RENDERPATH_D3D11:
14444                         RSurf_ActiveModelEntity(ent, true, true, false);
14445                         break;
14446                 case RENDERPATH_GL13:
14447                 case RENDERPATH_GL11:
14448                         RSurf_ActiveModelEntity(ent, true, false, false);
14449                         break;
14450                 }
14451         }
14452
14453         surfaces = model->data_surfaces;
14454         update = model->brushq1.lightmapupdateflags;
14455
14456         // update light styles
14457         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14458         {
14459                 model_brush_lightstyleinfo_t *style;
14460                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14461                 {
14462                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14463                         {
14464                                 int *list = style->surfacelist;
14465                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14466                                 for (j = 0;j < style->numsurfaces;j++)
14467                                         update[list[j]] = true;
14468                         }
14469                 }
14470         }
14471
14472         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14473
14474         if (debug)
14475         {
14476                 R_DrawDebugModel();
14477                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14478                 return;
14479         }
14480
14481         rsurface.lightmaptexture = NULL;
14482         rsurface.deluxemaptexture = NULL;
14483         rsurface.uselightmaptexture = false;
14484         rsurface.texture = NULL;
14485         rsurface.rtlight = NULL;
14486         numsurfacelist = 0;
14487         // add visible surfaces to draw list
14488         for (i = 0;i < model->nummodelsurfaces;i++)
14489                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14490         // don't do anything if there were no surfaces
14491         if (!numsurfacelist)
14492         {
14493                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14494                 return;
14495         }
14496         // update lightmaps if needed
14497         if (update)
14498         {
14499                 int updated = 0;
14500                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14501                 {
14502                         if (update[j])
14503                         {
14504                                 updated++;
14505                                 R_BuildLightMap(ent, surfaces + j);
14506                         }
14507                 }
14508         }
14509         if (update)
14510                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14511                         if (update[j])
14512                                 R_BuildLightMap(ent, surfaces + j);
14513         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14514         GL_AlphaTest(false);
14515
14516         // add to stats if desired
14517         if (r_speeds.integer && !skysurfaces && !depthonly)
14518         {
14519                 r_refdef.stats.entities_surfaces += numsurfacelist;
14520                 for (j = 0;j < numsurfacelist;j++)
14521                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14522         }
14523
14524         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14525 }
14526
14527 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14528 {
14529         static texture_t texture;
14530         static msurface_t surface;
14531         const msurface_t *surfacelist = &surface;
14532
14533         // fake enough texture and surface state to render this geometry
14534
14535         texture.update_lastrenderframe = -1; // regenerate this texture
14536         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14537         texture.currentskinframe = skinframe;
14538         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14539         texture.offsetmapping = OFFSETMAPPING_OFF;
14540         texture.offsetscale = 1;
14541         texture.specularscalemod = 1;
14542         texture.specularpowermod = 1;
14543
14544         surface.texture = &texture;
14545         surface.num_triangles = numtriangles;
14546         surface.num_firsttriangle = firsttriangle;
14547         surface.num_vertices = numvertices;
14548         surface.num_firstvertex = firstvertex;
14549
14550         // now render it
14551         rsurface.texture = R_GetCurrentTexture(surface.texture);
14552         rsurface.lightmaptexture = NULL;
14553         rsurface.deluxemaptexture = NULL;
14554         rsurface.uselightmaptexture = false;
14555         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14556 }
14557
14558 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)
14559 {
14560         static msurface_t surface;
14561         const msurface_t *surfacelist = &surface;
14562
14563         // fake enough texture and surface state to render this geometry
14564         surface.texture = texture;
14565         surface.num_triangles = numtriangles;
14566         surface.num_firsttriangle = firsttriangle;
14567         surface.num_vertices = numvertices;
14568         surface.num_firstvertex = firstvertex;
14569
14570         // now render it
14571         rsurface.texture = R_GetCurrentTexture(surface.texture);
14572         rsurface.lightmaptexture = NULL;
14573         rsurface.deluxemaptexture = NULL;
14574         rsurface.uselightmaptexture = false;
14575         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14576 }