]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix random white pixels with r_shadow_glossexact caused by unnormalized VectorS/T/R
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155
156 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
162
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
167
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
175
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
180
181 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
182
183 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
184
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
186
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194
195 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
196 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
197
198 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
199
200 extern cvar_t v_glslgamma;
201
202 extern qboolean v_flipped_state;
203
204 static struct r_bloomstate_s
205 {
206         qboolean enabled;
207         qboolean hdr;
208
209         int bloomwidth, bloomheight;
210
211         int screentexturewidth, screentextureheight;
212         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
213
214         int bloomtexturewidth, bloomtextureheight;
215         rtexture_t *texture_bloom;
216
217         // arrays for rendering the screen passes
218         float screentexcoord2f[8];
219         float bloomtexcoord2f[8];
220         float offsettexcoord2f[8];
221
222         r_viewport_t viewport;
223 }
224 r_bloomstate;
225
226 r_waterstate_t r_waterstate;
227
228 /// shadow volume bsp struct with automatically growing nodes buffer
229 svbsp_t r_svbsp;
230
231 rtexture_t *r_texture_blanknormalmap;
232 rtexture_t *r_texture_white;
233 rtexture_t *r_texture_grey128;
234 rtexture_t *r_texture_black;
235 rtexture_t *r_texture_notexture;
236 rtexture_t *r_texture_whitecube;
237 rtexture_t *r_texture_normalizationcube;
238 rtexture_t *r_texture_fogattenuation;
239 rtexture_t *r_texture_fogheighttexture;
240 rtexture_t *r_texture_gammaramps;
241 unsigned int r_texture_gammaramps_serial;
242 //rtexture_t *r_texture_fogintensity;
243 rtexture_t *r_texture_reflectcube;
244
245 // TODO: hash lookups?
246 typedef struct cubemapinfo_s
247 {
248         char basename[64];
249         rtexture_t *texture;
250 }
251 cubemapinfo_t;
252
253 int r_texture_numcubemaps;
254 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
255
256 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
257 unsigned int r_numqueries;
258 unsigned int r_maxqueries;
259
260 typedef struct r_qwskincache_s
261 {
262         char name[MAX_QPATH];
263         skinframe_t *skinframe;
264 }
265 r_qwskincache_t;
266
267 static r_qwskincache_t *r_qwskincache;
268 static int r_qwskincache_size;
269
270 /// vertex coordinates for a quad that covers the screen exactly
271 extern const float r_screenvertex3f[12];
272 extern const float r_d3dscreenvertex3f[12];
273 const float r_screenvertex3f[12] =
274 {
275         0, 0, 0,
276         1, 0, 0,
277         1, 1, 0,
278         0, 1, 0
279 };
280 const float r_d3dscreenvertex3f[12] =
281 {
282         0, 1, 0,
283         1, 1, 0,
284         1, 0, 0,
285         0, 0, 0
286 };
287
288 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
289 {
290         int i;
291         for (i = 0;i < verts;i++)
292         {
293                 out[0] = in[0] * r;
294                 out[1] = in[1] * g;
295                 out[2] = in[2] * b;
296                 out[3] = in[3];
297                 in += 4;
298                 out += 4;
299         }
300 }
301
302 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = r;
308                 out[1] = g;
309                 out[2] = b;
310                 out[3] = a;
311                 out += 4;
312         }
313 }
314
315 // FIXME: move this to client?
316 void FOG_clear(void)
317 {
318         if (gamemode == GAME_NEHAHRA)
319         {
320                 Cvar_Set("gl_fogenable", "0");
321                 Cvar_Set("gl_fogdensity", "0.2");
322                 Cvar_Set("gl_fogred", "0.3");
323                 Cvar_Set("gl_foggreen", "0.3");
324                 Cvar_Set("gl_fogblue", "0.3");
325         }
326         r_refdef.fog_density = 0;
327         r_refdef.fog_red = 0;
328         r_refdef.fog_green = 0;
329         r_refdef.fog_blue = 0;
330         r_refdef.fog_alpha = 1;
331         r_refdef.fog_start = 0;
332         r_refdef.fog_end = 16384;
333         r_refdef.fog_height = 1<<30;
334         r_refdef.fog_fadedepth = 128;
335         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
336 }
337
338 static void R_BuildBlankTextures(void)
339 {
340         unsigned char data[4];
341         data[2] = 128; // normal X
342         data[1] = 128; // normal Y
343         data[0] = 255; // normal Z
344         data[3] = 128; // height
345         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346         data[0] = 255;
347         data[1] = 255;
348         data[2] = 255;
349         data[3] = 255;
350         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351         data[0] = 128;
352         data[1] = 128;
353         data[2] = 128;
354         data[3] = 255;
355         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 0;
357         data[1] = 0;
358         data[2] = 0;
359         data[3] = 255;
360         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 }
362
363 static void R_BuildNoTexture(void)
364 {
365         int x, y;
366         unsigned char pix[16][16][4];
367         // this makes a light grey/dark grey checkerboard texture
368         for (y = 0;y < 16;y++)
369         {
370                 for (x = 0;x < 16;x++)
371                 {
372                         if ((y < 8) ^ (x < 8))
373                         {
374                                 pix[y][x][0] = 128;
375                                 pix[y][x][1] = 128;
376                                 pix[y][x][2] = 128;
377                                 pix[y][x][3] = 255;
378                         }
379                         else
380                         {
381                                 pix[y][x][0] = 64;
382                                 pix[y][x][1] = 64;
383                                 pix[y][x][2] = 64;
384                                 pix[y][x][3] = 255;
385                         }
386                 }
387         }
388         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
389 }
390
391 static void R_BuildWhiteCube(void)
392 {
393         unsigned char data[6*1*1*4];
394         memset(data, 255, sizeof(data));
395         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNormalizationCube(void)
399 {
400         int x, y, side;
401         vec3_t v;
402         vec_t s, t, intensity;
403 #define NORMSIZE 64
404         unsigned char *data;
405         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
406         for (side = 0;side < 6;side++)
407         {
408                 for (y = 0;y < NORMSIZE;y++)
409                 {
410                         for (x = 0;x < NORMSIZE;x++)
411                         {
412                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
413                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
414                                 switch(side)
415                                 {
416                                 default:
417                                 case 0:
418                                         v[0] = 1;
419                                         v[1] = -t;
420                                         v[2] = -s;
421                                         break;
422                                 case 1:
423                                         v[0] = -1;
424                                         v[1] = -t;
425                                         v[2] = s;
426                                         break;
427                                 case 2:
428                                         v[0] = s;
429                                         v[1] = 1;
430                                         v[2] = t;
431                                         break;
432                                 case 3:
433                                         v[0] = s;
434                                         v[1] = -1;
435                                         v[2] = -t;
436                                         break;
437                                 case 4:
438                                         v[0] = s;
439                                         v[1] = -t;
440                                         v[2] = 1;
441                                         break;
442                                 case 5:
443                                         v[0] = -s;
444                                         v[1] = -t;
445                                         v[2] = -1;
446                                         break;
447                                 }
448                                 intensity = 127.0f / sqrt(DotProduct(v, v));
449                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
450                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
451                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
452                                 data[((side*64+y)*64+x)*4+3] = 255;
453                         }
454                 }
455         }
456         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
457         Mem_Free(data);
458 }
459
460 static void R_BuildFogTexture(void)
461 {
462         int x, b;
463 #define FOGWIDTH 256
464         unsigned char data1[FOGWIDTH][4];
465         //unsigned char data2[FOGWIDTH][4];
466         double d, r, alpha;
467
468         r_refdef.fogmasktable_start = r_refdef.fog_start;
469         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
470         r_refdef.fogmasktable_range = r_refdef.fogrange;
471         r_refdef.fogmasktable_density = r_refdef.fog_density;
472
473         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
474         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
475         {
476                 d = (x * r - r_refdef.fogmasktable_start);
477                 if(developer_extra.integer)
478                         Con_DPrintf("%f ", d);
479                 d = max(0, d);
480                 if (r_fog_exp2.integer)
481                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
482                 else
483                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
484                 if(developer_extra.integer)
485                         Con_DPrintf(" : %f ", alpha);
486                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
487                 if(developer_extra.integer)
488                         Con_DPrintf(" = %f\n", alpha);
489                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
490         }
491
492         for (x = 0;x < FOGWIDTH;x++)
493         {
494                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495                 data1[x][0] = b;
496                 data1[x][1] = b;
497                 data1[x][2] = b;
498                 data1[x][3] = 255;
499                 //data2[x][0] = 255 - b;
500                 //data2[x][1] = 255 - b;
501                 //data2[x][2] = 255 - b;
502                 //data2[x][3] = 255;
503         }
504         if (r_texture_fogattenuation)
505         {
506                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
507                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
508         }
509         else
510         {
511                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
513         }
514 }
515
516 static void R_BuildFogHeightTexture(void)
517 {
518         unsigned char *inpixels;
519         int size;
520         int x;
521         int y;
522         int j;
523         float c[4];
524         float f;
525         inpixels = NULL;
526         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
527         if (r_refdef.fogheighttexturename[0])
528                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
529         if (!inpixels)
530         {
531                 r_refdef.fog_height_tablesize = 0;
532                 if (r_texture_fogheighttexture)
533                         R_FreeTexture(r_texture_fogheighttexture);
534                 r_texture_fogheighttexture = NULL;
535                 if (r_refdef.fog_height_table2d)
536                         Mem_Free(r_refdef.fog_height_table2d);
537                 r_refdef.fog_height_table2d = NULL;
538                 if (r_refdef.fog_height_table1d)
539                         Mem_Free(r_refdef.fog_height_table1d);
540                 r_refdef.fog_height_table1d = NULL;
541                 return;
542         }
543         size = image_width;
544         r_refdef.fog_height_tablesize = size;
545         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
546         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
547         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
548         Mem_Free(inpixels);
549         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
550         // average fog color table accounting for every fog layer between a point
551         // and the camera.  (Note: attenuation is handled separately!)
552         for (y = 0;y < size;y++)
553         {
554                 for (x = 0;x < size;x++)
555                 {
556                         Vector4Clear(c);
557                         f = 0;
558                         if (x < y)
559                         {
560                                 for (j = x;j <= y;j++)
561                                 {
562                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
563                                         f++;
564                                 }
565                         }
566                         else
567                         {
568                                 for (j = x;j >= y;j--)
569                                 {
570                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571                                         f++;
572                                 }
573                         }
574                         f = 1.0f / f;
575                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
576                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
577                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
579                 }
580         }
581         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
582 }
583
584 //=======================================================================================================================================================
585
586 static const char *builtinshaderstring =
587 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
588 "// written by Forest 'LordHavoc' Hale\n"
589 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
590 "\n"
591 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
592 "# define USEFOG\n"
593 "#endif\n"
594 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
595 "#define USELIGHTMAP\n"
596 "#endif\n"
597 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
598 "#define USEEYEVECTOR\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESHADOWMAP2D\n"
602 "# ifdef GL_EXT_gpu_shader4\n"
603 "#   extension GL_EXT_gpu_shader4 : enable\n"
604 "# endif\n"
605 "# ifdef GL_ARB_texture_gather\n"
606 "#   extension GL_ARB_texture_gather : enable\n"
607 "# else\n"
608 "#   ifdef GL_AMD_texture_texture4\n"
609 "#     extension GL_AMD_texture_texture4 : enable\n"
610 "#   endif\n"
611 "# endif\n"
612 "#endif\n"
613 "\n"
614 "//#ifdef USESHADOWSAMPLER\n"
615 "//# extension GL_ARB_shadow : enable\n"
616 "//#endif\n"
617 "\n"
618 "//#ifdef __GLSL_CG_DATA_TYPES\n"
619 "//# define myhalf half\n"
620 "//# define myhalf2 half2\n"
621 "//# define myhalf3 half3\n"
622 "//# define myhalf4 half4\n"
623 "//#else\n"
624 "# define myhalf float\n"
625 "# define myhalf2 vec2\n"
626 "# define myhalf3 vec3\n"
627 "# define myhalf4 vec4\n"
628 "//#endif\n"
629 "\n"
630 "#ifdef VERTEX_SHADER\n"
631 "uniform mat4 ModelViewProjectionMatrix;\n"
632 "#endif\n"
633 "\n"
634 "#ifdef MODE_DEPTH_OR_SHADOW\n"
635 "#ifdef VERTEX_SHADER\n"
636 "void main(void)\n"
637 "{\n"
638 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
639 "}\n"
640 "#endif\n"
641 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "\n"
643 "\n"
644 "\n"
645 "\n"
646 "#ifdef MODE_SHOWDEPTH\n"
647 "#ifdef VERTEX_SHADER\n"
648 "void main(void)\n"
649 "{\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
652 "}\n"
653 "#endif\n"
654 "\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "void main(void)\n"
657 "{\n"
658 "       gl_FragColor = gl_Color;\n"
659 "}\n"
660 "#endif\n"
661 "#else // !MODE_SHOWDEPTH\n"
662 "\n"
663 "\n"
664 "\n"
665 "\n"
666 "#ifdef MODE_POSTPROCESS\n"
667 "varying vec2 TexCoord1;\n"
668 "varying vec2 TexCoord2;\n"
669 "\n"
670 "#ifdef VERTEX_SHADER\n"
671 "void main(void)\n"
672 "{\n"
673 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
674 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
675 "#ifdef USEBLOOM\n"
676 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "\n"
681 "#ifdef FRAGMENT_SHADER\n"
682 "uniform sampler2D Texture_First;\n"
683 "#ifdef USEBLOOM\n"
684 "uniform sampler2D Texture_Second;\n"
685 "uniform vec4 BloomColorSubtract;\n"
686 "#endif\n"
687 "#ifdef USEGAMMARAMPS\n"
688 "uniform sampler2D Texture_GammaRamps;\n"
689 "#endif\n"
690 "#ifdef USESATURATION\n"
691 "uniform float Saturation;\n"
692 "#endif\n"
693 "#ifdef USEVIEWTINT\n"
694 "uniform vec4 ViewTintColor;\n"
695 "#endif\n"
696 "//uncomment these if you want to use them:\n"
697 "uniform vec4 UserVec1;\n"
698 "uniform vec4 UserVec2;\n"
699 "// uniform vec4 UserVec3;\n"
700 "// uniform vec4 UserVec4;\n"
701 "// uniform float ClientTime;\n"
702 "uniform vec2 PixelSize;\n"
703 "void main(void)\n"
704 "{\n"
705 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
706 "#ifdef USEBLOOM\n"
707 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
708 "#endif\n"
709 "#ifdef USEVIEWTINT\n"
710 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
711 "#endif\n"
712 "\n"
713 "#ifdef USEPOSTPROCESSING\n"
714 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
715 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
716 "       float sobel = 1.0;\n"
717 "       // vec2 ts = textureSize(Texture_First, 0);\n"
718 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
719 "       vec2 px = PixelSize;\n"
720 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
722 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
725 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
726 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
727 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
728 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
729 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
730 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
731 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
732 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
733 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
734 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
735 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
736 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
737 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
738 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
739 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
740 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
741 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
742 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
743 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
744 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
751 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
752 "#endif\n"
753 "\n"
754 "#ifdef USESATURATION\n"
755 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
756 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
757 "       // 'vampire sight' effect, wheres red is compensated\n"
758 "       #ifdef SATURATION_REDCOMPENSATE\n"
759 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
760 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
761 "               gl_FragColor.r += rboost;\n"
762 "       #else\n"
763 "               // normal desaturation\n"
764 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
765 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
766 "       #endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USEGAMMARAMPS\n"
770 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
771 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
772 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
773 "#endif\n"
774 "}\n"
775 "#endif\n"
776 "#else // !MODE_POSTPROCESS\n"
777 "\n"
778 "\n"
779 "\n"
780 "\n"
781 "#ifdef MODE_GENERIC\n"
782 "#ifdef USEDIFFUSE\n"
783 "varying vec2 TexCoord1;\n"
784 "#endif\n"
785 "#ifdef USESPECULAR\n"
786 "varying vec2 TexCoord2;\n"
787 "#endif\n"
788 "#ifdef VERTEX_SHADER\n"
789 "void main(void)\n"
790 "{\n"
791 "       gl_FrontColor = gl_Color;\n"
792 "#ifdef USEDIFFUSE\n"
793 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
797 "#endif\n"
798 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
799 "}\n"
800 "#endif\n"
801 "\n"
802 "#ifdef FRAGMENT_SHADER\n"
803 "#ifdef USEDIFFUSE\n"
804 "uniform sampler2D Texture_First;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "uniform sampler2D Texture_Second;\n"
808 "#endif\n"
809 "\n"
810 "void main(void)\n"
811 "{\n"
812 "#ifdef USEVIEWTINT\n"
813 "       gl_FragColor = gl_Color;\n"
814 "#else\n"
815 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
816 "#endif\n"
817 "#ifdef USEDIFFUSE\n"
818 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
819 "#endif\n"
820 "\n"
821 "#ifdef USESPECULAR\n"
822 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
823 "# ifdef USECOLORMAPPING\n"
824 "       gl_FragColor *= tex2;\n"
825 "# endif\n"
826 "# ifdef USEGLOW\n"
827 "       gl_FragColor += tex2;\n"
828 "# endif\n"
829 "# ifdef USEVERTEXTEXTUREBLEND\n"
830 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
831 "# endif\n"
832 "#endif\n"
833 "}\n"
834 "#endif\n"
835 "#else // !MODE_GENERIC\n"
836 "\n"
837 "\n"
838 "\n"
839 "\n"
840 "#ifdef MODE_BLOOMBLUR\n"
841 "varying TexCoord;\n"
842 "#ifdef VERTEX_SHADER\n"
843 "void main(void)\n"
844 "{\n"
845 "       gl_FrontColor = gl_Color;\n"
846 "       TexCoord = gl_MultiTexCoord0.xy;\n"
847 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
848 "}\n"
849 "#endif\n"
850 "\n"
851 "#ifdef FRAGMENT_SHADER\n"
852 "uniform sampler2D Texture_First;\n"
853 "uniform vec4 BloomBlur_Parameters;\n"
854 "\n"
855 "void main(void)\n"
856 "{\n"
857 "       int i;\n"
858 "       vec2 tc = TexCoord;\n"
859 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
860 "       tc += BloomBlur_Parameters.xy;\n"
861 "       for (i = 1;i < SAMPLES;i++)\n"
862 "       {\n"
863 "               color += texture2D(Texture_First, tc).rgb;\n"
864 "               tc += BloomBlur_Parameters.xy;\n"
865 "       }\n"
866 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
867 "}\n"
868 "#endif\n"
869 "#else // !MODE_BLOOMBLUR\n"
870 "#ifdef MODE_REFRACTION\n"
871 "varying vec2 TexCoord;\n"
872 "varying vec4 ModelViewProjectionPosition;\n"
873 "uniform mat4 TexMatrix;\n"
874 "#ifdef VERTEX_SHADER\n"
875 "\n"
876 "void main(void)\n"
877 "{\n"
878 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
879 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
880 "       ModelViewProjectionPosition = gl_Position;\n"
881 "}\n"
882 "#endif\n"
883 "\n"
884 "#ifdef FRAGMENT_SHADER\n"
885 "uniform sampler2D Texture_Normal;\n"
886 "uniform sampler2D Texture_Refraction;\n"
887 "uniform sampler2D Texture_Reflection;\n"
888 "\n"
889 "uniform vec4 DistortScaleRefractReflect;\n"
890 "uniform vec4 ScreenScaleRefractReflect;\n"
891 "uniform vec4 ScreenCenterRefractReflect;\n"
892 "uniform vec4 RefractColor;\n"
893 "uniform vec4 ReflectColor;\n"
894 "uniform float ReflectFactor;\n"
895 "uniform float ReflectOffset;\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
900 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
901 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
902 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
903 "       // FIXME temporary hack to detect the case that the reflection\n"
904 "       // gets blackened at edges due to leaving the area that contains actual\n"
905 "       // content.\n"
906 "       // Remove this 'ack once we have a better way to stop this thing from\n"
907 "       // 'appening.\n"
908 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
909 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
910 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
912 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
913 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
914 "}\n"
915 "#endif\n"
916 "#else // !MODE_REFRACTION\n"
917 "\n"
918 "\n"
919 "\n"
920 "\n"
921 "#ifdef MODE_WATER\n"
922 "varying vec2 TexCoord;\n"
923 "varying vec3 EyeVector;\n"
924 "varying vec4 ModelViewProjectionPosition;\n"
925 "#ifdef VERTEX_SHADER\n"
926 "uniform vec3 EyePosition;\n"
927 "uniform mat4 TexMatrix;\n"
928 "\n"
929 "void main(void)\n"
930 "{\n"
931 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
932 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
933 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
934 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
935 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
936 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
937 "       ModelViewProjectionPosition = gl_Position;\n"
938 "}\n"
939 "#endif\n"
940 "\n"
941 "#ifdef FRAGMENT_SHADER\n"
942 "uniform sampler2D Texture_Normal;\n"
943 "uniform sampler2D Texture_Refraction;\n"
944 "uniform sampler2D Texture_Reflection;\n"
945 "\n"
946 "uniform vec4 DistortScaleRefractReflect;\n"
947 "uniform vec4 ScreenScaleRefractReflect;\n"
948 "uniform vec4 ScreenCenterRefractReflect;\n"
949 "uniform vec4 RefractColor;\n"
950 "uniform vec4 ReflectColor;\n"
951 "uniform float ReflectFactor;\n"
952 "uniform float ReflectOffset;\n"
953 "uniform float ClientTime;\n"
954 "#ifdef USENORMALMAPSCROLLBLEND\n"
955 "uniform vec2 NormalmapScrollBlend;\n"
956 "#endif\n"
957 "\n"
958 "void main(void)\n"
959 "{\n"
960 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
961 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
962 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
963 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
964 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
965 "       #ifdef USENORMALMAPSCROLLBLEND\n"
966 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
967 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
968 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
969 "       #else\n"
970 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
971 "       #endif\n"
972 "       // FIXME temporary hack to detect the case that the reflection\n"
973 "       // gets blackened at edges due to leaving the area that contains actual\n"
974 "       // content.\n"
975 "       // Remove this 'ack once we have a better way to stop this thing from\n"
976 "       // 'appening.\n"
977 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
978 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
979 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
980 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
981 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
982 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
983 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
984 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
985 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
986 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
987 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
988 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
989 "       gl_FragColor.a = f1 + 0.5;\n"
990 "}\n"
991 "#endif\n"
992 "#else // !MODE_WATER\n"
993 "\n"
994 "\n"
995 "\n"
996 "\n"
997 "// common definitions between vertex shader and fragment shader:\n"
998 "\n"
999 "varying vec2 TexCoord;\n"
1000 "#ifdef USEVERTEXTEXTUREBLEND\n"
1001 "varying vec2 TexCoord2;\n"
1002 "#endif\n"
1003 "#ifdef USELIGHTMAP\n"
1004 "varying vec2 TexCoordLightmap;\n"
1005 "#endif\n"
1006 "\n"
1007 "#ifdef MODE_LIGHTSOURCE\n"
1008 "varying vec3 CubeVector;\n"
1009 "#endif\n"
1010 "\n"
1011 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1012 "varying vec3 LightVector;\n"
1013 "#endif\n"
1014 "\n"
1015 "#ifdef USEEYEVECTOR\n"
1016 "varying vec3 EyeVector;\n"
1017 "#endif\n"
1018 "#ifdef USEFOG\n"
1019 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1020 "#endif\n"
1021 "\n"
1022 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1023 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1024 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1025 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1026 "#endif\n"
1027 "\n"
1028 "#ifdef USEREFLECTION\n"
1029 "varying vec4 ModelViewProjectionPosition;\n"
1030 "#endif\n"
1031 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1032 "uniform vec3 LightPosition;\n"
1033 "varying vec4 ModelViewPosition;\n"
1034 "#endif\n"
1035 "\n"
1036 "#ifdef MODE_LIGHTSOURCE\n"
1037 "uniform vec3 LightPosition;\n"
1038 "#endif\n"
1039 "uniform vec3 EyePosition;\n"
1040 "#ifdef MODE_LIGHTDIRECTION\n"
1041 "uniform vec3 LightDir;\n"
1042 "#endif\n"
1043 "uniform vec4 FogPlane;\n"
1044 "\n"
1045 "#ifdef USESHADOWMAPORTHO\n"
1046 "varying vec3 ShadowMapTC;\n"
1047 "#endif\n"
1048 "\n"
1049 "\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "// 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"
1054 "\n"
1055 "// fragment shader specific:\n"
1056 "#ifdef FRAGMENT_SHADER\n"
1057 "\n"
1058 "uniform sampler2D Texture_Normal;\n"
1059 "uniform sampler2D Texture_Color;\n"
1060 "uniform sampler2D Texture_Gloss;\n"
1061 "#ifdef USEGLOW\n"
1062 "uniform sampler2D Texture_Glow;\n"
1063 "#endif\n"
1064 "#ifdef USEVERTEXTEXTUREBLEND\n"
1065 "uniform sampler2D Texture_SecondaryNormal;\n"
1066 "uniform sampler2D Texture_SecondaryColor;\n"
1067 "uniform sampler2D Texture_SecondaryGloss;\n"
1068 "#ifdef USEGLOW\n"
1069 "uniform sampler2D Texture_SecondaryGlow;\n"
1070 "#endif\n"
1071 "#endif\n"
1072 "#ifdef USECOLORMAPPING\n"
1073 "uniform sampler2D Texture_Pants;\n"
1074 "uniform sampler2D Texture_Shirt;\n"
1075 "#endif\n"
1076 "#ifdef USEFOG\n"
1077 "#ifdef USEFOGHEIGHTTEXTURE\n"
1078 "uniform sampler2D Texture_FogHeightTexture;\n"
1079 "#endif\n"
1080 "uniform sampler2D Texture_FogMask;\n"
1081 "#endif\n"
1082 "#ifdef USELIGHTMAP\n"
1083 "uniform sampler2D Texture_Lightmap;\n"
1084 "#endif\n"
1085 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1086 "uniform sampler2D Texture_Deluxemap;\n"
1087 "#endif\n"
1088 "#ifdef USEREFLECTION\n"
1089 "uniform sampler2D Texture_Reflection;\n"
1090 "#endif\n"
1091 "\n"
1092 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1093 "uniform sampler2D Texture_ScreenDepth;\n"
1094 "uniform sampler2D Texture_ScreenNormalMap;\n"
1095 "#endif\n"
1096 "#ifdef USEDEFERREDLIGHTMAP\n"
1097 "uniform sampler2D Texture_ScreenDiffuse;\n"
1098 "uniform sampler2D Texture_ScreenSpecular;\n"
1099 "#endif\n"
1100 "\n"
1101 "uniform myhalf3 Color_Pants;\n"
1102 "uniform myhalf3 Color_Shirt;\n"
1103 "uniform myhalf3 FogColor;\n"
1104 "\n"
1105 "#ifdef USEFOG\n"
1106 "uniform float FogRangeRecip;\n"
1107 "uniform float FogPlaneViewDist;\n"
1108 "uniform float FogHeightFade;\n"
1109 "vec3 FogVertex(vec3 surfacecolor)\n"
1110 "{\n"
1111 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1112 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1113 "       float fogfrac;\n"
1114 "#ifdef USEFOGHEIGHTTEXTURE\n"
1115 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1116 "       fogfrac = fogheightpixel.a;\n"
1117 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1118 "#else\n"
1119 "# ifdef USEFOGOUTSIDE\n"
1120 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1121 "# else\n"
1122 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1123 "# endif\n"
1124 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1125 "#endif\n"
1126 "}\n"
1127 "#endif\n"
1128 "\n"
1129 "#ifdef USEOFFSETMAPPING\n"
1130 "uniform float OffsetMapping_Scale;\n"
1131 "vec2 OffsetMapping(vec2 TexCoord)\n"
1132 "{\n"
1133 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1134 "       // 14 sample relief mapping: linear search and then binary search\n"
1135 "       // this basically steps forward a small amount repeatedly until it finds\n"
1136 "       // itself inside solid, then jitters forward and back using decreasing\n"
1137 "       // amounts to find the impact\n"
1138 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1139 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1140 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1141 "       vec3 RT = vec3(TexCoord, 1);\n"
1142 "       OffsetVector *= 0.1;\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1153 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1157 "       return RT.xy;\n"
1158 "#else\n"
1159 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1160 "       // this basically moves forward the full distance, and then backs up based\n"
1161 "       // on height of samples\n"
1162 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1163 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1164 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1165 "       TexCoord += OffsetVector;\n"
1166 "       OffsetVector *= 0.5;\n"
1167 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1168 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1169 "       return TexCoord;\n"
1170 "#endif\n"
1171 "}\n"
1172 "#endif // USEOFFSETMAPPING\n"
1173 "\n"
1174 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1175 "uniform sampler2D Texture_Attenuation;\n"
1176 "uniform samplerCube Texture_Cube;\n"
1177 "#endif\n"
1178 "\n"
1179 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1180 "\n"
1181 "#ifdef USESHADOWMAP2D\n"
1182 "# ifdef USESHADOWSAMPLER\n"
1183 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1184 "# else\n"
1185 "uniform sampler2D Texture_ShadowMap2D;\n"
1186 "# endif\n"
1187 "#endif\n"
1188 "\n"
1189 "#ifdef USESHADOWMAPVSDCT\n"
1190 "uniform samplerCube Texture_CubeProjection;\n"
1191 "#endif\n"
1192 "\n"
1193 "#if defined(USESHADOWMAP2D)\n"
1194 "uniform vec2 ShadowMap_TextureScale;\n"
1195 "uniform vec4 ShadowMap_Parameters;\n"
1196 "#endif\n"
1197 "\n"
1198 "#if defined(USESHADOWMAP2D)\n"
1199 "# ifdef USESHADOWMAPORTHO\n"
1200 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1201 "# else\n"
1202 "#  ifdef USESHADOWMAPVSDCT\n"
1203 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1204 "{\n"
1205 "       vec3 adir = abs(dir);\n"
1206 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1207 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1208 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1209 "}\n"
1210 "#  else\n"
1211 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1212 "{\n"
1213 "       vec3 adir = abs(dir);\n"
1214 "       float ma = adir.z;\n"
1215 "       vec4 proj = vec4(dir, 2.5);\n"
1216 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1217 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1218 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1219 "       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"
1220 "}\n"
1221 "#  endif\n"
1222 "# endif\n"
1223 "#endif // defined(USESHADOWMAP2D)\n"
1224 "\n"
1225 "# ifdef USESHADOWMAP2D\n"
1226 "float ShadowMapCompare(vec3 dir)\n"
1227 "{\n"
1228 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1229 "       float f;\n"
1230 "\n"
1231 "#  ifdef USESHADOWSAMPLER\n"
1232 "#    ifdef USESHADOWMAPPCF\n"
1233 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1234 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1235 "       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"
1236 "#    else\n"
1237 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1238 "#    endif\n"
1239 "#  else\n"
1240 "#    ifdef USESHADOWMAPPCF\n"
1241 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1242 "#      ifdef GL_ARB_texture_gather\n"
1243 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1244 "#      else\n"
1245 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1246 "#      endif\n"
1247 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1248 "#      if USESHADOWMAPPCF > 1\n"
1249 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1250 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1251 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1252 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1253 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1254 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1255 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1256 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1257 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1258 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1259 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1260 "       locols.yz += group2.ab;\n"
1261 "       hicols.yz += group8.rg;\n"
1262 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1263 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1264 "                               mix(locols, hicols, offset.y);\n"
1265 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1266 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1267 "       f = dot(cols, vec4(1.0/25.0));\n"
1268 "#      else\n"
1269 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1270 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1271 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1272 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1273 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1274 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1275 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1276 "#      endif\n"
1277 "#     else\n"
1278 "#      ifdef GL_EXT_gpu_shader4\n"
1279 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1280 "#      else\n"
1281 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1282 "#      endif\n"
1283 "#      if USESHADOWMAPPCF > 1\n"
1284 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1285 "       center *= ShadowMap_TextureScale;\n"
1286 "       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"
1287 "       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"
1288 "       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"
1289 "       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"
1290 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1291 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1292 "#      else\n"
1293 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1294 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1295 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1296 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1297 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1298 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1299 "#      endif\n"
1300 "#     endif\n"
1301 "#    else\n"
1302 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1303 "#    endif\n"
1304 "#  endif\n"
1305 "#  ifdef USESHADOWMAPORTHO\n"
1306 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1307 "#  else\n"
1308 "       return f;\n"
1309 "#  endif\n"
1310 "}\n"
1311 "# endif\n"
1312 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1313 "#endif // FRAGMENT_SHADER\n"
1314 "\n"
1315 "\n"
1316 "\n"
1317 "\n"
1318 "#ifdef MODE_DEFERREDGEOMETRY\n"
1319 "#ifdef VERTEX_SHADER\n"
1320 "uniform mat4 TexMatrix;\n"
1321 "#ifdef USEVERTEXTEXTUREBLEND\n"
1322 "uniform mat4 BackgroundTexMatrix;\n"
1323 "#endif\n"
1324 "uniform mat4 ModelViewMatrix;\n"
1325 "void main(void)\n"
1326 "{\n"
1327 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       gl_FrontColor = gl_Color;\n"
1330 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1331 "#endif\n"
1332 "\n"
1333 "       // transform unnormalized eye direction into tangent space\n"
1334 "#ifdef USEOFFSETMAPPING\n"
1335 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1336 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1337 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1338 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1339 "#endif\n"
1340 "\n"
1341 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1342 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1343 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1344 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1345 "}\n"
1346 "#endif // VERTEX_SHADER\n"
1347 "\n"
1348 "#ifdef FRAGMENT_SHADER\n"
1349 "void main(void)\n"
1350 "{\n"
1351 "#ifdef USEOFFSETMAPPING\n"
1352 "       // apply offsetmapping\n"
1353 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1354 "#define TexCoord TexCoordOffset\n"
1355 "#endif\n"
1356 "\n"
1357 "#ifdef USEALPHAKILL\n"
1358 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1359 "               discard;\n"
1360 "#endif\n"
1361 "\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1364 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1365 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1366 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1367 "#endif\n"
1368 "\n"
1369 "#ifdef USEVERTEXTEXTUREBLEND\n"
1370 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1371 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1372 "#else\n"
1373 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1374 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1375 "#endif\n"
1376 "\n"
1377 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1378 "}\n"
1379 "#endif // FRAGMENT_SHADER\n"
1380 "#else // !MODE_DEFERREDGEOMETRY\n"
1381 "\n"
1382 "\n"
1383 "\n"
1384 "\n"
1385 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1386 "#ifdef VERTEX_SHADER\n"
1387 "uniform mat4 ModelViewMatrix;\n"
1388 "void main(void)\n"
1389 "{\n"
1390 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1391 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1392 "}\n"
1393 "#endif // VERTEX_SHADER\n"
1394 "\n"
1395 "#ifdef FRAGMENT_SHADER\n"
1396 "uniform mat4 ViewToLight;\n"
1397 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1398 "uniform vec2 ScreenToDepth;\n"
1399 "uniform myhalf3 DeferredColor_Ambient;\n"
1400 "uniform myhalf3 DeferredColor_Diffuse;\n"
1401 "#ifdef USESPECULAR\n"
1402 "uniform myhalf3 DeferredColor_Specular;\n"
1403 "uniform myhalf SpecularPower;\n"
1404 "#endif\n"
1405 "uniform myhalf2 PixelToScreenTexCoord;\n"
1406 "void main(void)\n"
1407 "{\n"
1408 "       // calculate viewspace pixel position\n"
1409 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1410 "       vec3 position;\n"
1411 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1412 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1413 "       // decode viewspace pixel normal\n"
1414 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1415 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1416 "       // surfacenormal = pixel normal in viewspace\n"
1417 "       // LightVector = pixel to light in viewspace\n"
1418 "       // CubeVector = position in lightspace\n"
1419 "       // eyevector = pixel to view in viewspace\n"
1420 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1421 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1422 "#ifdef USEDIFFUSE\n"
1423 "       // calculate diffuse shading\n"
1424 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1425 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1426 "#endif\n"
1427 "#ifdef USESPECULAR\n"
1428 "       // calculate directional shading\n"
1429 "       vec3 eyevector = position * -1.0;\n"
1430 "#  ifdef USEEXACTSPECULARMATH\n"
1431 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1432 "#  else\n"
1433 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1434 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1435 "#  endif\n"
1436 "#endif\n"
1437 "\n"
1438 "#if defined(USESHADOWMAP2D)\n"
1439 "       fade *= ShadowMapCompare(CubeVector);\n"
1440 "#endif\n"
1441 "\n"
1442 "#ifdef USEDIFFUSE\n"
1443 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1444 "#else\n"
1445 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1446 "#endif\n"
1447 "#ifdef USESPECULAR\n"
1448 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1449 "#else\n"
1450 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1451 "#endif\n"
1452 "\n"
1453 "# ifdef USECUBEFILTER\n"
1454 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1455 "       gl_FragData[0].rgb *= cubecolor;\n"
1456 "       gl_FragData[1].rgb *= cubecolor;\n"
1457 "# endif\n"
1458 "}\n"
1459 "#endif // FRAGMENT_SHADER\n"
1460 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1461 "\n"
1462 "\n"
1463 "\n"
1464 "\n"
1465 "#ifdef VERTEX_SHADER\n"
1466 "uniform mat4 TexMatrix;\n"
1467 "#ifdef USEVERTEXTEXTUREBLEND\n"
1468 "uniform mat4 BackgroundTexMatrix;\n"
1469 "#endif\n"
1470 "#ifdef MODE_LIGHTSOURCE\n"
1471 "uniform mat4 ModelToLight;\n"
1472 "#endif\n"
1473 "#ifdef USESHADOWMAPORTHO\n"
1474 "uniform mat4 ShadowMapMatrix;\n"
1475 "#endif\n"
1476 "void main(void)\n"
1477 "{\n"
1478 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1479 "       gl_FrontColor = gl_Color;\n"
1480 "#endif\n"
1481 "       // copy the surface texcoord\n"
1482 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1483 "#ifdef USEVERTEXTEXTUREBLEND\n"
1484 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1485 "#endif\n"
1486 "#ifdef USELIGHTMAP\n"
1487 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1488 "#endif\n"
1489 "\n"
1490 "#ifdef MODE_LIGHTSOURCE\n"
1491 "       // transform vertex position into light attenuation/cubemap space\n"
1492 "       // (-1 to +1 across the light box)\n"
1493 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1494 "\n"
1495 "# ifdef USEDIFFUSE\n"
1496 "       // transform unnormalized light direction into tangent space\n"
1497 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1498 "       //  normalize it per pixel)\n"
1499 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1500 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1501 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1502 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1503 "# endif\n"
1504 "#endif\n"
1505 "\n"
1506 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1507 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1508 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1509 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1510 "#endif\n"
1511 "\n"
1512 "       // transform unnormalized eye direction into tangent space\n"
1513 "#ifdef USEEYEVECTOR\n"
1514 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1515 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1516 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1517 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1518 "#endif\n"
1519 "\n"
1520 "#ifdef USEFOG\n"
1521 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1522 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1523 "#endif\n"
1524 "\n"
1525 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1526 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1527 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1528 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1529 "#endif\n"
1530 "\n"
1531 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1532 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1533 "\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1536 "#endif\n"
1537 "\n"
1538 "#ifdef USEREFLECTION\n"
1539 "       ModelViewProjectionPosition = gl_Position;\n"
1540 "#endif\n"
1541 "}\n"
1542 "#endif // VERTEX_SHADER\n"
1543 "\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "#ifdef FRAGMENT_SHADER\n"
1548 "#ifdef USEDEFERREDLIGHTMAP\n"
1549 "uniform myhalf2 PixelToScreenTexCoord;\n"
1550 "uniform myhalf3 DeferredMod_Diffuse;\n"
1551 "uniform myhalf3 DeferredMod_Specular;\n"
1552 "#endif\n"
1553 "uniform myhalf3 Color_Ambient;\n"
1554 "uniform myhalf3 Color_Diffuse;\n"
1555 "uniform myhalf3 Color_Specular;\n"
1556 "uniform myhalf SpecularPower;\n"
1557 "#ifdef USEGLOW\n"
1558 "uniform myhalf3 Color_Glow;\n"
1559 "#endif\n"
1560 "uniform myhalf Alpha;\n"
1561 "#ifdef USEREFLECTION\n"
1562 "uniform vec4 DistortScaleRefractReflect;\n"
1563 "uniform vec4 ScreenScaleRefractReflect;\n"
1564 "uniform vec4 ScreenCenterRefractReflect;\n"
1565 "uniform myhalf4 ReflectColor;\n"
1566 "#endif\n"
1567 "#ifdef USEREFLECTCUBE\n"
1568 "uniform mat4 ModelToReflectCube;\n"
1569 "uniform sampler2D Texture_ReflectMask;\n"
1570 "uniform samplerCube Texture_ReflectCube;\n"
1571 "#endif\n"
1572 "#ifdef MODE_LIGHTDIRECTION\n"
1573 "uniform myhalf3 LightColor;\n"
1574 "#endif\n"
1575 "#ifdef MODE_LIGHTSOURCE\n"
1576 "uniform myhalf3 LightColor;\n"
1577 "#endif\n"
1578 "void main(void)\n"
1579 "{\n"
1580 "#ifdef USEOFFSETMAPPING\n"
1581 "       // apply offsetmapping\n"
1582 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1583 "#define TexCoord TexCoordOffset\n"
1584 "#endif\n"
1585 "\n"
1586 "       // combine the diffuse textures (base, pants, shirt)\n"
1587 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1588 "#ifdef USEALPHAKILL\n"
1589 "       if (color.a < 0.5)\n"
1590 "               discard;\n"
1591 "#endif\n"
1592 "       color.a *= Alpha;\n"
1593 "#ifdef USECOLORMAPPING\n"
1594 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1595 "#endif\n"
1596 "#ifdef USEVERTEXTEXTUREBLEND\n"
1597 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1598 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1599 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1600 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1601 "       color.a = 1.0;\n"
1602 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1603 "#endif\n"
1604 "\n"
1605 "       // get the surface normal\n"
1606 "#ifdef USEVERTEXTEXTUREBLEND\n"
1607 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1608 "#else\n"
1609 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#endif\n"
1611 "\n"
1612 "       // get the material colors\n"
1613 "       myhalf3 diffusetex = color.rgb;\n"
1614 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1615 "# ifdef USEVERTEXTEXTUREBLEND\n"
1616 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1617 "# else\n"
1618 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1619 "# endif\n"
1620 "#endif\n"
1621 "\n"
1622 "#ifdef USEREFLECTCUBE\n"
1623 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1624 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1625 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1626 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1627 "#endif\n"
1628 "\n"
1629 "\n"
1630 "\n"
1631 "\n"
1632 "#ifdef MODE_LIGHTSOURCE\n"
1633 "       // light source\n"
1634 "#ifdef USEDIFFUSE\n"
1635 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1636 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1637 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1638 "#ifdef USESPECULAR\n"
1639 "#ifdef USEEXACTSPECULARMATH\n"
1640 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1641 "#else\n"
1642 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1643 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1644 "#endif\n"
1645 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1646 "#endif\n"
1647 "#else\n"
1648 "       color.rgb = diffusetex * Color_Ambient;\n"
1649 "#endif\n"
1650 "       color.rgb *= LightColor;\n"
1651 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1652 "#if defined(USESHADOWMAP2D)\n"
1653 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1654 "#endif\n"
1655 "# ifdef USECUBEFILTER\n"
1656 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1657 "# endif\n"
1658 "#endif // MODE_LIGHTSOURCE\n"
1659 "\n"
1660 "\n"
1661 "\n"
1662 "\n"
1663 "#ifdef MODE_LIGHTDIRECTION\n"
1664 "#define SHADING\n"
1665 "#ifdef USEDIFFUSE\n"
1666 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1667 "#endif\n"
1668 "#define lightcolor LightColor\n"
1669 "#endif // MODE_LIGHTDIRECTION\n"
1670 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1671 "#define SHADING\n"
1672 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1673 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1674 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1675 "       // convert modelspace light vector to tangentspace\n"
1676 "       myhalf3 lightnormal;\n"
1677 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1678 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1679 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1680 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1681 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1682 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1683 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1684 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1685 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1686 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1687 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1688 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1689 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1690 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1691 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1692 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1693 "#define SHADING\n"
1694 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1695 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1696 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1697 "#endif\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_FAKELIGHT\n"
1703 "#define SHADING\n"
1704 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1705 "myhalf3 lightcolor = myhalf3(1.0);\n"
1706 "#endif // MODE_FAKELIGHT\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "#ifdef MODE_LIGHTMAP\n"
1712 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1713 "#endif // MODE_LIGHTMAP\n"
1714 "#ifdef MODE_VERTEXCOLOR\n"
1715 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1716 "#endif // MODE_VERTEXCOLOR\n"
1717 "#ifdef MODE_FLATCOLOR\n"
1718 "       color.rgb = diffusetex * Color_Ambient;\n"
1719 "#endif // MODE_FLATCOLOR\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef SHADING\n"
1725 "# ifdef USEDIFFUSE\n"
1726 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1727 "#  ifdef USESPECULAR\n"
1728 "#   ifdef USEEXACTSPECULARMATH\n"
1729 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1730 "#   else\n"
1731 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1732 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1733 "#   endif\n"
1734 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1735 "#  else\n"
1736 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1737 "#  endif\n"
1738 "# else\n"
1739 "       color.rgb = diffusetex * Color_Ambient;\n"
1740 "# endif\n"
1741 "#endif\n"
1742 "\n"
1743 "#ifdef USESHADOWMAPORTHO\n"
1744 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef USEDEFERREDLIGHTMAP\n"
1748 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1749 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1750 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1751 "#endif\n"
1752 "\n"
1753 "#ifdef USEGLOW\n"
1754 "#ifdef USEVERTEXTEXTUREBLEND\n"
1755 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1756 "#else\n"
1757 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1758 "#endif\n"
1759 "#endif\n"
1760 "\n"
1761 "#ifdef USEFOG\n"
1762 "       color.rgb = FogVertex(color.rgb);\n"
1763 "#endif\n"
1764 "\n"
1765 "       // 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"
1766 "#ifdef USEREFLECTION\n"
1767 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1768 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1769 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1770 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1771 "       // FIXME temporary hack to detect the case that the reflection\n"
1772 "       // gets blackened at edges due to leaving the area that contains actual\n"
1773 "       // content.\n"
1774 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1775 "       // 'appening.\n"
1776 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1777 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1778 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1780 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1781 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1782 "#endif\n"
1783 "\n"
1784 "       gl_FragColor = vec4(color);\n"
1785 "}\n"
1786 "#endif // FRAGMENT_SHADER\n"
1787 "\n"
1788 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1789 "#endif // !MODE_DEFERREDGEOMETRY\n"
1790 "#endif // !MODE_WATER\n"
1791 "#endif // !MODE_REFRACTION\n"
1792 "#endif // !MODE_BLOOMBLUR\n"
1793 "#endif // !MODE_GENERIC\n"
1794 "#endif // !MODE_POSTPROCESS\n"
1795 "#endif // !MODE_SHOWDEPTH\n"
1796 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1797 ;
1798
1799 /*
1800 =========================================================================================================================================================
1801
1802
1803
1804 =========================================================================================================================================================
1805
1806
1807
1808 =========================================================================================================================================================
1809
1810
1811
1812 =========================================================================================================================================================
1813
1814
1815
1816 =========================================================================================================================================================
1817
1818
1819
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825 */
1826
1827 const char *builtincgshaderstring =
1828 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1829 "// written by Forest 'LordHavoc' Hale\n"
1830 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1831 "\n"
1832 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1833 "#if defined(USEREFLECTION)\n"
1834 "#undef USESHADOWMAPORTHO\n"
1835 "#endif\n"
1836 "\n"
1837 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1838 "# define USEFOG\n"
1839 "#endif\n"
1840 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1841 "#define USELIGHTMAP\n"
1842 "#endif\n"
1843 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1844 "#define USEEYEVECTOR\n"
1845 "#endif\n"
1846 "\n"
1847 "#ifdef FRAGMENT_SHADER\n"
1848 "#ifdef HLSL\n"
1849 "//#undef USESHADOWMAPPCF\n"
1850 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1851 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1852 "#else\n"
1853 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1854 "#endif\n"
1855 "#endif\n"
1856 "\n"
1857 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1858 "#ifdef VERTEX_SHADER\n"
1859 "void main\n"
1860 "(\n"
1861 "float4 gl_Vertex : POSITION,\n"
1862 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1863 "out float4 gl_Position : POSITION,\n"
1864 "out float Depth : TEXCOORD0\n"
1865 ")\n"
1866 "{\n"
1867 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1868 "       Depth = gl_Position.z;\n"
1869 "}\n"
1870 "#endif\n"
1871 "\n"
1872 "#ifdef FRAGMENT_SHADER\n"
1873 "void main\n"
1874 "(\n"
1875 "float Depth : TEXCOORD0,\n"
1876 "out float4 gl_FragColor : COLOR\n"
1877 ")\n"
1878 "{\n"
1879 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1880 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1881 "       temp.yz -= floor(temp.yz);\n"
1882 "       gl_FragColor = temp;\n"
1883 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1884 "}\n"
1885 "#endif\n"
1886 "#else // !MODE_DEPTH_ORSHADOW\n"
1887 "\n"
1888 "\n"
1889 "\n"
1890 "\n"
1891 "#ifdef MODE_SHOWDEPTH\n"
1892 "#ifdef VERTEX_SHADER\n"
1893 "void main\n"
1894 "(\n"
1895 "float4 gl_Vertex : POSITION,\n"
1896 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1897 "out float4 gl_Position : POSITION,\n"
1898 "out float4 gl_FrontColor : COLOR0\n"
1899 ")\n"
1900 "{\n"
1901 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1902 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1903 "}\n"
1904 "#endif\n"
1905 "\n"
1906 "#ifdef FRAGMENT_SHADER\n"
1907 "void main\n"
1908 "(\n"
1909 "float4 gl_FrontColor : COLOR0,\n"
1910 "out float4 gl_FragColor : COLOR\n"
1911 ")\n"
1912 "{\n"
1913 "       gl_FragColor = gl_FrontColor;\n"
1914 "}\n"
1915 "#endif\n"
1916 "#else // !MODE_SHOWDEPTH\n"
1917 "\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "#ifdef MODE_POSTPROCESS\n"
1922 "\n"
1923 "#ifdef VERTEX_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float4 gl_Vertex : POSITION,\n"
1927 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1928 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1929 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1930 "out float4 gl_Position : POSITION,\n"
1931 "out float2 TexCoord1 : TEXCOORD0,\n"
1932 "out float2 TexCoord2 : TEXCOORD1\n"
1933 ")\n"
1934 "{\n"
1935 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1936 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1937 "#ifdef USEBLOOM\n"
1938 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1939 "#endif\n"
1940 "}\n"
1941 "#endif\n"
1942 "\n"
1943 "#ifdef FRAGMENT_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float2 TexCoord1 : TEXCOORD0,\n"
1947 "float2 TexCoord2 : TEXCOORD1,\n"
1948 "uniform sampler Texture_First : register(s0),\n"
1949 "#ifdef USEBLOOM\n"
1950 "uniform sampler Texture_Second : register(s1),\n"
1951 "#endif\n"
1952 "#ifdef USEGAMMARAMPS\n"
1953 "uniform sampler Texture_GammaRamps : register(s2),\n"
1954 "#endif\n"
1955 "#ifdef USESATURATION\n"
1956 "uniform float Saturation : register(c30),\n"
1957 "#endif\n"
1958 "#ifdef USEVIEWTINT\n"
1959 "uniform float4 ViewTintColor : register(c41),\n"
1960 "#endif\n"
1961 "uniform float4 UserVec1 : register(c37),\n"
1962 "uniform float4 UserVec2 : register(c38),\n"
1963 "uniform float4 UserVec3 : register(c39),\n"
1964 "uniform float4 UserVec4 : register(c40),\n"
1965 "uniform float ClientTime : register(c2),\n"
1966 "uniform float2 PixelSize : register(c25),\n"
1967 "uniform float4 BloomColorSubtract : register(c43),\n"
1968 "out float4 gl_FragColor : COLOR\n"
1969 ")\n"
1970 "{\n"
1971 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1972 "#ifdef USEBLOOM\n"
1973 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1974 "#endif\n"
1975 "#ifdef USEVIEWTINT\n"
1976 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1977 "#endif\n"
1978 "\n"
1979 "#ifdef USEPOSTPROCESSING\n"
1980 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1981 "// 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"
1982 "       float sobel = 1.0;\n"
1983 "       // float2 ts = textureSize(Texture_First, 0);\n"
1984 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1985 "       float2 px = PixelSize;\n"
1986 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1987 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1988 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1989 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1990 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1991 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1992 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1993 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1994 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1995 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1996 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1997 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1998 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1999 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2000 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2001 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2002 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2003 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2004 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2005 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2006 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2007 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2008 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2009 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2010 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2011 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2012 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2016 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2017 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2018 "#endif\n"
2019 "\n"
2020 "#ifdef USESATURATION\n"
2021 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2022 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2023 "       // 'vampire sight' effect, wheres red is compensated\n"
2024 "       #ifdef SATURATION_REDCOMPENSATE\n"
2025 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2026 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2027 "               gl_FragColor.r += r;\n"
2028 "       #else\n"
2029 "               // normal desaturation\n"
2030 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2031 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2032 "       #endif\n"
2033 "#endif\n"
2034 "\n"
2035 "#ifdef USEGAMMARAMPS\n"
2036 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2037 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2038 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2039 "#endif\n"
2040 "}\n"
2041 "#endif\n"
2042 "#else // !MODE_POSTPROCESS\n"
2043 "\n"
2044 "\n"
2045 "\n"
2046 "\n"
2047 "#ifdef MODE_GENERIC\n"
2048 "#ifdef VERTEX_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float4 gl_Vertex : POSITION,\n"
2052 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2053 "float4 gl_Color : COLOR0,\n"
2054 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2055 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2056 "out float4 gl_Position : POSITION,\n"
2057 "#ifdef USEDIFFUSE\n"
2058 "out float2 TexCoord1 : TEXCOORD0,\n"
2059 "#endif\n"
2060 "#ifdef USESPECULAR\n"
2061 "out float2 TexCoord2 : TEXCOORD1,\n"
2062 "#endif\n"
2063 "out float4 gl_FrontColor : COLOR\n"
2064 ")\n"
2065 "{\n"
2066 "#ifdef HLSL\n"
2067 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2068 "#else\n"
2069 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2070 "#endif\n"
2071 "#ifdef USEDIFFUSE\n"
2072 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2073 "#endif\n"
2074 "#ifdef USESPECULAR\n"
2075 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2076 "#endif\n"
2077 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2078 "}\n"
2079 "#endif\n"
2080 "\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2082 "\n"
2083 "void main\n"
2084 "(\n"
2085 "float4 gl_FrontColor : COLOR0,\n"
2086 "float2 TexCoord1 : TEXCOORD0,\n"
2087 "float2 TexCoord2 : TEXCOORD1,\n"
2088 "#ifdef USEDIFFUSE\n"
2089 "uniform sampler Texture_First : register(s0),\n"
2090 "#endif\n"
2091 "#ifdef USESPECULAR\n"
2092 "uniform sampler Texture_Second : register(s1),\n"
2093 "#endif\n"
2094 "out float4 gl_FragColor : COLOR\n"
2095 ")\n"
2096 "{\n"
2097 "#ifdef USEVIEWTINT\n"
2098 "       gl_FragColor = gl_FrontColor;\n"
2099 "#else\n"
2100 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2101 "#endif\n"
2102 "#ifdef USEDIFFUSE\n"
2103 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2104 "#endif\n"
2105 "\n"
2106 "#ifdef USESPECULAR\n"
2107 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2108 "# ifdef USECOLORMAPPING\n"
2109 "       gl_FragColor *= tex2;\n"
2110 "# endif\n"
2111 "# ifdef USEGLOW\n"
2112 "       gl_FragColor += tex2;\n"
2113 "# endif\n"
2114 "# ifdef USEVERTEXTEXTUREBLEND\n"
2115 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2116 "# endif\n"
2117 "#endif\n"
2118 "}\n"
2119 "#endif\n"
2120 "#else // !MODE_GENERIC\n"
2121 "\n"
2122 "\n"
2123 "\n"
2124 "\n"
2125 "#ifdef MODE_BLOOMBLUR\n"
2126 "#ifdef VERTEX_SHADER\n"
2127 "void main\n"
2128 "(\n"
2129 "float4 gl_Vertex : POSITION,\n"
2130 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2131 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2132 "out float4 gl_Position : POSITION,\n"
2133 "out float2 TexCoord : TEXCOORD0\n"
2134 ")\n"
2135 "{\n"
2136 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2137 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2138 "}\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef FRAGMENT_SHADER\n"
2142 "\n"
2143 "void main\n"
2144 "(\n"
2145 "float2 TexCoord : TEXCOORD0,\n"
2146 "uniform sampler Texture_First : register(s0),\n"
2147 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2148 "out float4 gl_FragColor : COLOR\n"
2149 ")\n"
2150 "{\n"
2151 "       int i;\n"
2152 "       float2 tc = TexCoord;\n"
2153 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2154 "       tc += BloomBlur_Parameters.xy;\n"
2155 "       for (i = 1;i < SAMPLES;i++)\n"
2156 "       {\n"
2157 "               color += tex2D(Texture_First, tc).rgb;\n"
2158 "               tc += BloomBlur_Parameters.xy;\n"
2159 "       }\n"
2160 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2161 "}\n"
2162 "#endif\n"
2163 "#else // !MODE_BLOOMBLUR\n"
2164 "#ifdef MODE_REFRACTION\n"
2165 "#ifdef VERTEX_SHADER\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "uniform float4x4 TexMatrix : register(c0),\n"
2172 "uniform float3 EyePosition : register(c24),\n"
2173 "out float4 gl_Position : POSITION,\n"
2174 "out float2 TexCoord : TEXCOORD0,\n"
2175 "out float3 EyeVector : TEXCOORD1,\n"
2176 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2177 ")\n"
2178 "{\n"
2179 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2180 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2181 "       ModelViewProjectionPosition = gl_Position;\n"
2182 "}\n"
2183 "#endif\n"
2184 "\n"
2185 "#ifdef FRAGMENT_SHADER\n"
2186 "void main\n"
2187 "(\n"
2188 "float2 TexCoord : TEXCOORD0,\n"
2189 "float3 EyeVector : TEXCOORD1,\n"
2190 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2191 "uniform sampler Texture_Normal : register(s0),\n"
2192 "uniform sampler Texture_Refraction : register(s3),\n"
2193 "uniform sampler Texture_Reflection : register(s7),\n"
2194 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2195 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2196 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2197 "uniform float4 RefractColor : register(c29),\n"
2198 "out float4 gl_FragColor : COLOR\n"
2199 ")\n"
2200 "{\n"
2201 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2202 "       //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"
2203 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2204 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2205 "       // FIXME temporary hack to detect the case that the reflection\n"
2206 "       // gets blackened at edges due to leaving the area that contains actual\n"
2207 "       // content.\n"
2208 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2209 "       // 'appening.\n"
2210 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2211 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2212 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2214 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2215 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2216 "}\n"
2217 "#endif\n"
2218 "#else // !MODE_REFRACTION\n"
2219 "\n"
2220 "\n"
2221 "\n"
2222 "\n"
2223 "#ifdef MODE_WATER\n"
2224 "#ifdef VERTEX_SHADER\n"
2225 "\n"
2226 "void main\n"
2227 "(\n"
2228 "float4 gl_Vertex : POSITION,\n"
2229 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2230 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2231 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2232 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2233 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2234 "uniform float4x4 TexMatrix : register(c0),\n"
2235 "uniform float3 EyePosition : register(c24),\n"
2236 "out float4 gl_Position : POSITION,\n"
2237 "out float2 TexCoord : TEXCOORD0,\n"
2238 "out float3 EyeVector : TEXCOORD1,\n"
2239 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2240 ")\n"
2241 "{\n"
2242 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2243 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2244 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2245 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2246 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2247 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2248 "       ModelViewProjectionPosition = gl_Position;\n"
2249 "}\n"
2250 "#endif\n"
2251 "\n"
2252 "#ifdef FRAGMENT_SHADER\n"
2253 "void main\n"
2254 "(\n"
2255 "float2 TexCoord : TEXCOORD0,\n"
2256 "float3 EyeVector : TEXCOORD1,\n"
2257 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2258 "uniform sampler Texture_Normal : register(s0),\n"
2259 "uniform sampler Texture_Refraction : register(s3),\n"
2260 "uniform sampler Texture_Reflection : register(s7),\n"
2261 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2262 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2263 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2264 "uniform float4 RefractColor : register(c29),\n"
2265 "uniform float4 ReflectColor : register(c26),\n"
2266 "uniform float ReflectFactor : register(c27),\n"
2267 "uniform float ReflectOffset : register(c28),\n"
2268 "out float4 gl_FragColor : COLOR\n"
2269 ")\n"
2270 "{\n"
2271 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2272 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2273 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2274 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2275 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2276 "       // FIXME temporary hack to detect the case that the reflection\n"
2277 "       // gets blackened at edges due to leaving the area that contains actual\n"
2278 "       // content.\n"
2279 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2280 "       // 'appening.\n"
2281 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2282 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2283 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2285 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2286 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2287 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2288 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2289 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2290 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2291 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2292 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2293 "}\n"
2294 "#endif\n"
2295 "#else // !MODE_WATER\n"
2296 "\n"
2297 "\n"
2298 "\n"
2299 "\n"
2300 "// 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"
2301 "\n"
2302 "// fragment shader specific:\n"
2303 "#ifdef FRAGMENT_SHADER\n"
2304 "\n"
2305 "#ifdef USEFOG\n"
2306 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2307 "{\n"
2308 "       float fogfrac;\n"
2309 "#ifdef USEFOGHEIGHTTEXTURE\n"
2310 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2311 "       fogfrac = fogheightpixel.a;\n"
2312 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2313 "#else\n"
2314 "# ifdef USEFOGOUTSIDE\n"
2315 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2316 "# else\n"
2317 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2318 "# endif\n"
2319 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2320 "#endif\n"
2321 "}\n"
2322 "#endif\n"
2323 "\n"
2324 "#ifdef USEOFFSETMAPPING\n"
2325 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2326 "{\n"
2327 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2328 "       // 14 sample relief mapping: linear search and then binary search\n"
2329 "       // this basically steps forward a small amount repeatedly until it finds\n"
2330 "       // itself inside solid, then jitters forward and back using decreasing\n"
2331 "       // amounts to find the impact\n"
2332 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2333 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2334 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2335 "       float3 RT = float3(TexCoord, 1);\n"
2336 "       OffsetVector *= 0.1;\n"
2337 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2338 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2347 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2351 "       return RT.xy;\n"
2352 "#else\n"
2353 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2354 "       // this basically moves forward the full distance, and then backs up based\n"
2355 "       // on height of samples\n"
2356 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2357 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2358 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2359 "       TexCoord += OffsetVector;\n"
2360 "       OffsetVector *= 0.333;\n"
2361 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2362 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       return TexCoord;\n"
2365 "#endif\n"
2366 "}\n"
2367 "#endif // USEOFFSETMAPPING\n"
2368 "\n"
2369 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2370 "#if defined(USESHADOWMAP2D)\n"
2371 "# ifdef USESHADOWMAPORTHO\n"
2372 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2373 "# else\n"
2374 "#  ifdef USESHADOWMAPVSDCT\n"
2375 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2376 "{\n"
2377 "       float3 adir = abs(dir);\n"
2378 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2379 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2380 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2381 "}\n"
2382 "#  else\n"
2383 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2384 "{\n"
2385 "       float3 adir = abs(dir);\n"
2386 "       float ma = adir.z;\n"
2387 "       float4 proj = float4(dir, 2.5);\n"
2388 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2389 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2390 "#ifdef HLSL\n"
2391 "       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"
2392 "#else\n"
2393 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2394 "       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"
2395 "#endif\n"
2396 "}\n"
2397 "#  endif\n"
2398 "# endif\n"
2399 "#endif // defined(USESHADOWMAP2D)\n"
2400 "\n"
2401 "# ifdef USESHADOWMAP2D\n"
2402 "#ifdef USESHADOWMAPVSDCT\n"
2403 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2404 "#else\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2406 "#endif\n"
2407 "{\n"
2408 "#ifdef USESHADOWMAPVSDCT\n"
2409 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2410 "#else\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2412 "#endif\n"
2413 "       float f;\n"
2414 "\n"
2415 "#  ifdef USESHADOWSAMPLER\n"
2416 "#    ifdef USESHADOWMAPPCF\n"
2417 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2418 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2419 "       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"
2420 "#    else\n"
2421 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2422 "#    endif\n"
2423 "#  else\n"
2424 "#    ifdef USESHADOWMAPPCF\n"
2425 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2426 "#      ifdef GL_ARB_texture_gather\n"
2427 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2428 "#      else\n"
2429 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2430 "#      endif\n"
2431 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2432 "#      if USESHADOWMAPPCF > 1\n"
2433 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2434 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2435 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2436 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2437 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2438 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2439 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2440 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2441 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2442 "       float4 locols = float4(group1.ab, group3.ab);\n"
2443 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2444 "       locols.yz += group2.ab;\n"
2445 "       hicols.yz += group8.rg;\n"
2446 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2447 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2448 "                               lerp(locols, hicols, offset.y);\n"
2449 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2450 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2451 "       f = dot(cols, float4(1.0/25.0));\n"
2452 "#      else\n"
2453 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2454 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2455 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2456 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2457 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2458 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2459 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2460 "#      endif\n"
2461 "#     else\n"
2462 "#      ifdef GL_EXT_gpu_shader4\n"
2463 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2464 "#      else\n"
2465 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2466 "#      endif\n"
2467 "#      if USESHADOWMAPPCF > 1\n"
2468 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2469 "       center *= ShadowMap_TextureScale;\n"
2470 "       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"
2471 "       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"
2472 "       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"
2473 "       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"
2474 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2475 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2476 "#      else\n"
2477 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2478 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2479 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2480 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2481 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2482 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2483 "#      endif\n"
2484 "#     endif\n"
2485 "#    else\n"
2486 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2487 "#    endif\n"
2488 "#  endif\n"
2489 "#  ifdef USESHADOWMAPORTHO\n"
2490 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2491 "#  else\n"
2492 "       return f;\n"
2493 "#  endif\n"
2494 "}\n"
2495 "# endif\n"
2496 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2497 "#endif // FRAGMENT_SHADER\n"
2498 "\n"
2499 "\n"
2500 "\n"
2501 "\n"
2502 "#ifdef MODE_DEFERREDGEOMETRY\n"
2503 "#ifdef VERTEX_SHADER\n"
2504 "void main\n"
2505 "(\n"
2506 "float4 gl_Vertex : POSITION,\n"
2507 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2508 "#ifdef USEVERTEXTEXTUREBLEND\n"
2509 "float4 gl_Color : COLOR0,\n"
2510 "#endif\n"
2511 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2512 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2513 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2514 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2515 "uniform float4x4 TexMatrix : register(c0),\n"
2516 "#ifdef USEVERTEXTEXTUREBLEND\n"
2517 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2518 "#endif\n"
2519 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2520 "#ifdef USEOFFSETMAPPING\n"
2521 "uniform float3 EyePosition : register(c24),\n"
2522 "#endif\n"
2523 "out float4 gl_Position : POSITION,\n"
2524 "#ifdef USEVERTEXTEXTUREBLEND\n"
2525 "out float4 gl_FrontColor : COLOR,\n"
2526 "#endif\n"
2527 "out float4 TexCoordBoth : TEXCOORD0,\n"
2528 "#ifdef USEOFFSETMAPPING\n"
2529 "out float3 EyeVector : TEXCOORD2,\n"
2530 "#endif\n"
2531 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2532 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2533 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2534 ")\n"
2535 "{\n"
2536 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2537 "#ifdef USEVERTEXTEXTUREBLEND\n"
2538 "#ifdef HLSL\n"
2539 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2540 "#else\n"
2541 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2542 "#endif\n"
2543 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2544 "#endif\n"
2545 "\n"
2546 "       // transform unnormalized eye direction into tangent space\n"
2547 "#ifdef USEOFFSETMAPPING\n"
2548 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2549 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2550 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2551 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2552 "#endif\n"
2553 "\n"
2554 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2555 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2556 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2557 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2558 "       VectorR.w = gl_Position.z;\n"
2559 "}\n"
2560 "#endif // VERTEX_SHADER\n"
2561 "\n"
2562 "#ifdef FRAGMENT_SHADER\n"
2563 "void main\n"
2564 "(\n"
2565 "float4 TexCoordBoth : TEXCOORD0,\n"
2566 "float3 EyeVector : TEXCOORD2,\n"
2567 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2568 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2569 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2570 "uniform sampler Texture_Normal : register(s0),\n"
2571 "#ifdef USEALPHAKILL\n"
2572 "uniform sampler Texture_Color : register(s1),\n"
2573 "#endif\n"
2574 "uniform sampler Texture_Gloss : register(s2),\n"
2575 "#ifdef USEVERTEXTEXTUREBLEND\n"
2576 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2577 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2578 "#endif\n"
2579 "#ifdef USEOFFSETMAPPING\n"
2580 "uniform float OffsetMapping_Scale : register(c24),\n"
2581 "#endif\n"
2582 "uniform half SpecularPower : register(c36),\n"
2583 "#ifdef HLSL\n"
2584 "out float4 gl_FragData0 : COLOR0,\n"
2585 "out float4 gl_FragData1 : COLOR1\n"
2586 "#else\n"
2587 "out float4 gl_FragColor : COLOR\n"
2588 "#endif\n"
2589 ")\n"
2590 "{\n"
2591 "       float2 TexCoord = TexCoordBoth.xy;\n"
2592 "#ifdef USEOFFSETMAPPING\n"
2593 "       // apply offsetmapping\n"
2594 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2595 "#define TexCoord TexCoordOffset\n"
2596 "#endif\n"
2597 "\n"
2598 "#ifdef USEALPHAKILL\n"
2599 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2600 "               discard;\n"
2601 "#endif\n"
2602 "\n"
2603 "#ifdef USEVERTEXTEXTUREBLEND\n"
2604 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2605 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2606 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2607 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2608 "#endif\n"
2609 "\n"
2610 "#ifdef USEVERTEXTEXTUREBLEND\n"
2611 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2612 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2613 "#else\n"
2614 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2615 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2616 "#endif\n"
2617 "\n"
2618 "#ifdef HLSL\n"
2619 "       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"
2620 "       float Depth = VectorR.w / 256.0;\n"
2621 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2622 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2623 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2624 "       gl_FragData1 = depthcolor;\n"
2625 "#else\n"
2626 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2627 "#endif\n"
2628 "}\n"
2629 "#endif // FRAGMENT_SHADER\n"
2630 "#else // !MODE_DEFERREDGEOMETRY\n"
2631 "\n"
2632 "\n"
2633 "\n"
2634 "\n"
2635 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2636 "#ifdef VERTEX_SHADER\n"
2637 "void main\n"
2638 "(\n"
2639 "float4 gl_Vertex : POSITION,\n"
2640 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2641 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2642 "out float4 gl_Position : POSITION,\n"
2643 "out float4 ModelViewPosition : TEXCOORD0\n"
2644 ")\n"
2645 "{\n"
2646 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2647 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2648 "}\n"
2649 "#endif // VERTEX_SHADER\n"
2650 "\n"
2651 "#ifdef FRAGMENT_SHADER\n"
2652 "void main\n"
2653 "(\n"
2654 "#ifdef HLSL\n"
2655 "float2 Pixel : VPOS,\n"
2656 "#else\n"
2657 "float2 Pixel : WPOS,\n"
2658 "#endif\n"
2659 "float4 ModelViewPosition : TEXCOORD0,\n"
2660 "uniform float4x4 ViewToLight : register(c44),\n"
2661 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2662 "uniform float3 LightPosition : register(c23),\n"
2663 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2664 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2665 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2666 "#ifdef USESPECULAR\n"
2667 "uniform half3 DeferredColor_Specular : register(c11),\n"
2668 "uniform half SpecularPower : register(c36),\n"
2669 "#endif\n"
2670 "uniform sampler Texture_Attenuation : register(s9),\n"
2671 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2672 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2673 "\n"
2674 "#ifdef USECUBEFILTER\n"
2675 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2676 "#endif\n"
2677 "\n"
2678 "#ifdef USESHADOWMAP2D\n"
2679 "# ifdef USESHADOWSAMPLER\n"
2680 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2681 "# else\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# endif\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef USESHADOWMAPVSDCT\n"
2687 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(USESHADOWMAP2D)\n"
2691 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2692 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2693 "#endif\n"
2694 "\n"
2695 "out float4 gl_FragData0 : COLOR0,\n"
2696 "out float4 gl_FragData1 : COLOR1\n"
2697 ")\n"
2698 "{\n"
2699 "       // calculate viewspace pixel position\n"
2700 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2701 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2702 "       float3 position;\n"
2703 "#ifdef HLSL\n"
2704 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2705 "#else\n"
2706 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2707 "#endif\n"
2708 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2709 "       // decode viewspace pixel normal\n"
2710 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2711 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2712 "       // surfacenormal = pixel normal in viewspace\n"
2713 "       // LightVector = pixel to light in viewspace\n"
2714 "       // CubeVector = position in lightspace\n"
2715 "       // eyevector = pixel to view in viewspace\n"
2716 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2717 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2718 "#ifdef USEDIFFUSE\n"
2719 "       // calculate diffuse shading\n"
2720 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2721 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2722 "#endif\n"
2723 "#ifdef USESPECULAR\n"
2724 "       // calculate directional shading\n"
2725 "       float3 eyevector = position * -1.0;\n"
2726 "#  ifdef USEEXACTSPECULARMATH\n"
2727 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2728 "#  else\n"
2729 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2730 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2731 "#  endif\n"
2732 "#endif\n"
2733 "\n"
2734 "#if defined(USESHADOWMAP2D)\n"
2735 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2736 "#ifdef USESHADOWMAPVSDCT\n"
2737 ", Texture_CubeProjection\n"
2738 "#endif\n"
2739 "       ));\n"
2740 "#endif\n"
2741 "\n"
2742 "#ifdef USEDIFFUSE\n"
2743 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2744 "#else\n"
2745 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2746 "#endif\n"
2747 "#ifdef USESPECULAR\n"
2748 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2749 "#else\n"
2750 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2751 "#endif\n"
2752 "\n"
2753 "# ifdef USECUBEFILTER\n"
2754 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2755 "       gl_FragData0.rgb *= cubecolor;\n"
2756 "       gl_FragData1.rgb *= cubecolor;\n"
2757 "# endif\n"
2758 "}\n"
2759 "#endif // FRAGMENT_SHADER\n"
2760 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2761 "\n"
2762 "\n"
2763 "\n"
2764 "\n"
2765 "#ifdef VERTEX_SHADER\n"
2766 "void main\n"
2767 "(\n"
2768 "float4 gl_Vertex : POSITION,\n"
2769 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2770 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2771 "float4 gl_Color : COLOR0,\n"
2772 "#endif\n"
2773 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2774 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2775 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2776 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2777 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2778 "\n"
2779 "uniform float3 EyePosition : register(c24),\n"
2780 "uniform float4x4 TexMatrix : register(c0),\n"
2781 "#ifdef USEVERTEXTEXTUREBLEND\n"
2782 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2783 "#endif\n"
2784 "#ifdef MODE_LIGHTSOURCE\n"
2785 "uniform float4x4 ModelToLight : register(c20),\n"
2786 "#endif\n"
2787 "#ifdef MODE_LIGHTSOURCE\n"
2788 "uniform float3 LightPosition : register(c27),\n"
2789 "#endif\n"
2790 "#ifdef MODE_LIGHTDIRECTION\n"
2791 "uniform float3 LightDir : register(c26),\n"
2792 "#endif\n"
2793 "uniform float4 FogPlane : register(c25),\n"
2794 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2795 "uniform float3 LightPosition : register(c27),\n"
2796 "#endif\n"
2797 "#ifdef USESHADOWMAPORTHO\n"
2798 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2799 "#endif\n"
2800 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2801 "out float4 gl_FrontColor : COLOR,\n"
2802 "#endif\n"
2803 "out float4 TexCoordBoth : TEXCOORD0,\n"
2804 "#ifdef USELIGHTMAP\n"
2805 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2806 "#endif\n"
2807 "#ifdef USEEYEVECTOR\n"
2808 "out float3 EyeVector : TEXCOORD2,\n"
2809 "#endif\n"
2810 "#ifdef USEREFLECTION\n"
2811 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2812 "#endif\n"
2813 "#ifdef USEFOG\n"
2814 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2815 "#endif\n"
2816 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2817 "out float3 LightVector : TEXCOORD1,\n"
2818 "#endif\n"
2819 "#ifdef MODE_LIGHTSOURCE\n"
2820 "out float3 CubeVector : TEXCOORD3,\n"
2821 "#endif\n"
2822 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2823 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2824 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2825 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2826 "#endif\n"
2827 "#ifdef USESHADOWMAPORTHO\n"
2828 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2829 "#endif\n"
2830 "out float4 gl_Position : POSITION\n"
2831 ")\n"
2832 "{\n"
2833 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2834 "#ifdef HLSL\n"
2835 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2836 "#else\n"
2837 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2838 "#endif\n"
2839 "#endif\n"
2840 "       // copy the surface texcoord\n"
2841 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2842 "#ifdef USEVERTEXTEXTUREBLEND\n"
2843 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2844 "#endif\n"
2845 "#ifdef USELIGHTMAP\n"
2846 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2847 "#endif\n"
2848 "\n"
2849 "#ifdef MODE_LIGHTSOURCE\n"
2850 "       // transform vertex position into light attenuation/cubemap space\n"
2851 "       // (-1 to +1 across the light box)\n"
2852 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2853 "\n"
2854 "# ifdef USEDIFFUSE\n"
2855 "       // transform unnormalized light direction into tangent space\n"
2856 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2857 "       //  normalize it per pixel)\n"
2858 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2859 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2860 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2861 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2862 "# endif\n"
2863 "#endif\n"
2864 "\n"
2865 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2866 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2867 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2868 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2869 "#endif\n"
2870 "\n"
2871 "       // transform unnormalized eye direction into tangent space\n"
2872 "#ifdef USEEYEVECTOR\n"
2873 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2874 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2875 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2876 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USEFOG\n"
2880 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2882 "#endif\n"
2883 "\n"
2884 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2885 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2886 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2887 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2888 "#endif\n"
2889 "\n"
2890 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2892 "\n"
2893 "#ifdef USESHADOWMAPORTHO\n"
2894 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2895 "#endif\n"
2896 "\n"
2897 "#ifdef USEREFLECTION\n"
2898 "       ModelViewProjectionPosition = gl_Position;\n"
2899 "#endif\n"
2900 "}\n"
2901 "#endif // VERTEX_SHADER\n"
2902 "\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "#ifdef FRAGMENT_SHADER\n"
2907 "void main\n"
2908 "(\n"
2909 "#ifdef USEDEFERREDLIGHTMAP\n"
2910 "#ifdef HLSL\n"
2911 "float2 Pixel : VPOS,\n"
2912 "#else\n"
2913 "float2 Pixel : WPOS,\n"
2914 "#endif\n"
2915 "#endif\n"
2916 "float4 gl_FrontColor : COLOR,\n"
2917 "float4 TexCoordBoth : TEXCOORD0,\n"
2918 "#ifdef USELIGHTMAP\n"
2919 "float2 TexCoordLightmap : TEXCOORD1,\n"
2920 "#endif\n"
2921 "#ifdef USEEYEVECTOR\n"
2922 "float3 EyeVector : TEXCOORD2,\n"
2923 "#endif\n"
2924 "#ifdef USEREFLECTION\n"
2925 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2926 "#endif\n"
2927 "#ifdef USEFOG\n"
2928 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2929 "#endif\n"
2930 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2931 "float3 LightVector : TEXCOORD1,\n"
2932 "#endif\n"
2933 "#ifdef MODE_LIGHTSOURCE\n"
2934 "float3 CubeVector : TEXCOORD3,\n"
2935 "#endif\n"
2936 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2937 "float4 ModelViewPosition : TEXCOORD0,\n"
2938 "#endif\n"
2939 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2940 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2941 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2942 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2943 "#endif\n"
2944 "#ifdef USESHADOWMAPORTHO\n"
2945 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2946 "#endif\n"
2947 "\n"
2948 "uniform sampler Texture_Normal : register(s0),\n"
2949 "uniform sampler Texture_Color : register(s1),\n"
2950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2951 "uniform sampler Texture_Gloss : register(s2),\n"
2952 "#endif\n"
2953 "#ifdef USEGLOW\n"
2954 "uniform sampler Texture_Glow : register(s3),\n"
2955 "#endif\n"
2956 "#ifdef USEVERTEXTEXTUREBLEND\n"
2957 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2958 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2959 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2960 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2961 "#endif\n"
2962 "#ifdef USEGLOW\n"
2963 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2964 "#endif\n"
2965 "#endif\n"
2966 "#ifdef USECOLORMAPPING\n"
2967 "uniform sampler Texture_Pants : register(s4),\n"
2968 "uniform sampler Texture_Shirt : register(s7),\n"
2969 "#endif\n"
2970 "#ifdef USEFOG\n"
2971 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2972 "uniform sampler Texture_FogMask : register(s8),\n"
2973 "#endif\n"
2974 "#ifdef USELIGHTMAP\n"
2975 "uniform sampler Texture_Lightmap : register(s9),\n"
2976 "#endif\n"
2977 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2978 "uniform sampler Texture_Deluxemap : register(s10),\n"
2979 "#endif\n"
2980 "#ifdef USEREFLECTION\n"
2981 "uniform sampler Texture_Reflection : register(s7),\n"
2982 "#endif\n"
2983 "\n"
2984 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2985 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2986 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2987 "#endif\n"
2988 "#ifdef USEDEFERREDLIGHTMAP\n"
2989 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2990 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2991 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2992 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2993 "#endif\n"
2994 "\n"
2995 "#ifdef USECOLORMAPPING\n"
2996 "uniform half3 Color_Pants : register(c7),\n"
2997 "uniform half3 Color_Shirt : register(c8),\n"
2998 "#endif\n"
2999 "#ifdef USEFOG\n"
3000 "uniform float3 FogColor : register(c16),\n"
3001 "uniform float FogRangeRecip : register(c20),\n"
3002 "uniform float FogPlaneViewDist : register(c19),\n"
3003 "uniform float FogHeightFade : register(c17),\n"
3004 "#endif\n"
3005 "\n"
3006 "#ifdef USEOFFSETMAPPING\n"
3007 "uniform float OffsetMapping_Scale : register(c24),\n"
3008 "#endif\n"
3009 "\n"
3010 "#ifdef USEDEFERREDLIGHTMAP\n"
3011 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3012 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3013 "uniform half3 DeferredMod_Specular : register(c13),\n"
3014 "#endif\n"
3015 "uniform half3 Color_Ambient : register(c3),\n"
3016 "uniform half3 Color_Diffuse : register(c4),\n"
3017 "uniform half3 Color_Specular : register(c5),\n"
3018 "uniform half SpecularPower : register(c36),\n"
3019 "#ifdef USEGLOW\n"
3020 "uniform half3 Color_Glow : register(c6),\n"
3021 "#endif\n"
3022 "uniform half Alpha : register(c0),\n"
3023 "#ifdef USEREFLECTION\n"
3024 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3025 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3026 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3027 "uniform half4 ReflectColor : register(c26),\n"
3028 "#endif\n"
3029 "#ifdef USEREFLECTCUBE\n"
3030 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3031 "uniform sampler Texture_ReflectMask : register(s5),\n"
3032 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3033 "#endif\n"
3034 "#ifdef MODE_LIGHTDIRECTION\n"
3035 "uniform half3 LightColor : register(c21),\n"
3036 "#endif\n"
3037 "#ifdef MODE_LIGHTSOURCE\n"
3038 "uniform half3 LightColor : register(c21),\n"
3039 "#endif\n"
3040 "\n"
3041 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3042 "uniform sampler Texture_Attenuation : register(s9),\n"
3043 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3044 "#endif\n"
3045 "\n"
3046 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3047 "\n"
3048 "#ifdef USESHADOWMAP2D\n"
3049 "# ifdef USESHADOWSAMPLER\n"
3050 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3051 "# else\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# endif\n"
3054 "#endif\n"
3055 "\n"
3056 "#ifdef USESHADOWMAPVSDCT\n"
3057 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3058 "#endif\n"
3059 "\n"
3060 "#if defined(USESHADOWMAP2D)\n"
3061 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3062 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3063 "#endif\n"
3064 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3065 "\n"
3066 "out float4 gl_FragColor : COLOR\n"
3067 ")\n"
3068 "{\n"
3069 "       float2 TexCoord = TexCoordBoth.xy;\n"
3070 "#ifdef USEVERTEXTEXTUREBLEND\n"
3071 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3072 "#endif\n"
3073 "#ifdef USEOFFSETMAPPING\n"
3074 "       // apply offsetmapping\n"
3075 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3076 "#define TexCoord TexCoordOffset\n"
3077 "#endif\n"
3078 "\n"
3079 "       // combine the diffuse textures (base, pants, shirt)\n"
3080 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3081 "#ifdef USEALPHAKILL\n"
3082 "       if (color.a < 0.5)\n"
3083 "               discard;\n"
3084 "#endif\n"
3085 "       color.a *= Alpha;\n"
3086 "#ifdef USECOLORMAPPING\n"
3087 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3088 "#endif\n"
3089 "#ifdef USEVERTEXTEXTUREBLEND\n"
3090 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3091 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3092 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3093 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3094 "       color.a = 1.0;\n"
3095 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3096 "#endif\n"
3097 "\n"
3098 "       // get the surface normal\n"
3099 "#ifdef USEVERTEXTEXTUREBLEND\n"
3100 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3101 "#else\n"
3102 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3103 "#endif\n"
3104 "\n"
3105 "       // get the material colors\n"
3106 "       half3 diffusetex = color.rgb;\n"
3107 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3108 "# ifdef USEVERTEXTEXTUREBLEND\n"
3109 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3110 "# else\n"
3111 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3112 "# endif\n"
3113 "#endif\n"
3114 "\n"
3115 "#ifdef USEREFLECTCUBE\n"
3116 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3117 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3118 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3119 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3120 "#endif\n"
3121 "\n"
3122 "\n"
3123 "\n"
3124 "\n"
3125 "#ifdef MODE_LIGHTSOURCE\n"
3126 "       // light source\n"
3127 "#ifdef USEDIFFUSE\n"
3128 "       half3 lightnormal = half3(normalize(LightVector));\n"
3129 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3130 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3131 "#ifdef USESPECULAR\n"
3132 "#ifdef USEEXACTSPECULARMATH\n"
3133 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3134 "#else\n"
3135 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3136 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3137 "#endif\n"
3138 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3139 "#endif\n"
3140 "#else\n"
3141 "       color.rgb = diffusetex * Color_Ambient;\n"
3142 "#endif\n"
3143 "       color.rgb *= LightColor;\n"
3144 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3145 "#if defined(USESHADOWMAP2D)\n"
3146 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3147 "#ifdef USESHADOWMAPVSDCT\n"
3148 ", Texture_CubeProjection\n"
3149 "#endif\n"
3150 "       ));\n"
3151 "\n"
3152 "#endif\n"
3153 "# ifdef USECUBEFILTER\n"
3154 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3155 "# endif\n"
3156 "\n"
3157 "#ifdef USESHADOWMAP2D\n"
3158 "#ifdef USESHADOWMAPVSDCT\n"
3159 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3160 "#else\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3162 "#endif\n"
3163 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3164 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3165 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3166 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3167 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3168 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3169 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3170 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3171 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3172 "//     color.r = half(shadowmaptc.z);\n"
3173 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = 1;\n"
3176 "//     color.rgb = abs(CubeVector);\n"
3177 "#endif\n"
3178 "//     color.rgb = half3(1,1,1);\n"
3179 "#endif // MODE_LIGHTSOURCE\n"
3180 "\n"
3181 "\n"
3182 "\n"
3183 "\n"
3184 "#ifdef MODE_LIGHTDIRECTION\n"
3185 "#define SHADING\n"
3186 "#ifdef USEDIFFUSE\n"
3187 "       half3 lightnormal = half3(normalize(LightVector));\n"
3188 "#endif\n"
3189 "#define lightcolor LightColor\n"
3190 "#endif // MODE_LIGHTDIRECTION\n"
3191 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3192 "#define SHADING\n"
3193 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3194 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3195 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3196 "       // convert modelspace light vector to tangentspace\n"
3197 "       half3 lightnormal;\n"
3198 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3199 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3200 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3201 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3202 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3203 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3204 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3205 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3206 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3207 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3208 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3209 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3210 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3211 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3212 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3213 "#define SHADING\n"
3214 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3215 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3216 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3217 "#endif\n"
3218 "\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "#ifdef MODE_FAKELIGHT\n"
3223 "#define SHADING\n"
3224 "half3 lightnormal = half3(normalize(EyeVector));\n"
3225 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3226 "#endif // MODE_FAKELIGHT\n"
3227 "\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "#ifdef MODE_LIGHTMAP\n"
3232 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3233 "#endif // MODE_LIGHTMAP\n"
3234 "#ifdef MODE_VERTEXCOLOR\n"
3235 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3236 "#endif // MODE_VERTEXCOLOR\n"
3237 "#ifdef MODE_FLATCOLOR\n"
3238 "       color.rgb = diffusetex * Color_Ambient;\n"
3239 "#endif // MODE_FLATCOLOR\n"
3240 "\n"
3241 "\n"
3242 "\n"
3243 "\n"
3244 "#ifdef SHADING\n"
3245 "# ifdef USEDIFFUSE\n"
3246 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3247 "#  ifdef USESPECULAR\n"
3248 "#   ifdef USEEXACTSPECULARMATH\n"
3249 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3250 "#   else\n"
3251 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3252 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3253 "#   endif\n"
3254 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3255 "#  else\n"
3256 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3257 "#  endif\n"
3258 "# else\n"
3259 "       color.rgb = diffusetex * Color_Ambient;\n"
3260 "# endif\n"
3261 "#endif\n"
3262 "\n"
3263 "#ifdef USESHADOWMAPORTHO\n"
3264 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3265 "#endif\n"
3266 "\n"
3267 "#ifdef USEDEFERREDLIGHTMAP\n"
3268 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3269 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3270 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3271 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3272 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3273 "#endif\n"
3274 "\n"
3275 "#ifdef USEGLOW\n"
3276 "#ifdef USEVERTEXTEXTUREBLEND\n"
3277 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3278 "#else\n"
3279 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3280 "#endif\n"
3281 "#endif\n"
3282 "\n"
3283 "#ifdef USEFOG\n"
3284 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3285 "#endif\n"
3286 "\n"
3287 "       // 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"
3288 "#ifdef USEREFLECTION\n"
3289 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3290 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3291 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3292 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3293 "       // FIXME temporary hack to detect the case that the reflection\n"
3294 "       // gets blackened at edges due to leaving the area that contains actual\n"
3295 "       // content.\n"
3296 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3297 "       // 'appening.\n"
3298 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3299 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3300 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3302 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3303 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3304 "#endif\n"
3305 "\n"
3306 "       gl_FragColor = float4(color);\n"
3307 "}\n"
3308 "#endif // FRAGMENT_SHADER\n"
3309 "\n"
3310 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3311 "#endif // !MODE_DEFERREDGEOMETRY\n"
3312 "#endif // !MODE_WATER\n"
3313 "#endif // !MODE_REFRACTION\n"
3314 "#endif // !MODE_BLOOMBLUR\n"
3315 "#endif // !MODE_GENERIC\n"
3316 "#endif // !MODE_POSTPROCESS\n"
3317 "#endif // !MODE_SHOWDEPTH\n"
3318 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3319 ;
3320
3321 char *glslshaderstring = NULL;
3322 char *cgshaderstring = NULL;
3323 char *hlslshaderstring = NULL;
3324
3325 //=======================================================================================================================================================
3326
3327 typedef struct shaderpermutationinfo_s
3328 {
3329         const char *pretext;
3330         const char *name;
3331 }
3332 shaderpermutationinfo_t;
3333
3334 typedef struct shadermodeinfo_s
3335 {
3336         const char *vertexfilename;
3337         const char *geometryfilename;
3338         const char *fragmentfilename;
3339         const char *pretext;
3340         const char *name;
3341 }
3342 shadermodeinfo_t;
3343
3344 typedef enum shaderpermutation_e
3345 {
3346         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3347         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3348         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3349         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3350         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3351         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3352         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3353         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3354         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3355         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3356         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3357         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3358         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3359         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3360         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3361         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3362         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3363         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3364         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3365         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3366         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3367         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3368         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3369         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3370         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3371         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3372         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3373         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3374         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3375 }
3376 shaderpermutation_t;
3377
3378 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3379 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3380 {
3381         {"#define USEDIFFUSE\n", " diffuse"},
3382         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3383         {"#define USEVIEWTINT\n", " viewtint"},
3384         {"#define USECOLORMAPPING\n", " colormapping"},
3385         {"#define USESATURATION\n", " saturation"},
3386         {"#define USEFOGINSIDE\n", " foginside"},
3387         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3388         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3389         {"#define USEGAMMARAMPS\n", " gammaramps"},
3390         {"#define USECUBEFILTER\n", " cubefilter"},
3391         {"#define USEGLOW\n", " glow"},
3392         {"#define USEBLOOM\n", " bloom"},
3393         {"#define USESPECULAR\n", " specular"},
3394         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3395         {"#define USEREFLECTION\n", " reflection"},
3396         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3397         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3398         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3399         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3400         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3401         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3402         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3403         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3404         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3405         {"#define USEALPHAKILL\n", " alphakill"},
3406         {"#define USEREFLECTCUBE\n", " reflectcube"},
3407         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3408 };
3409
3410 // this enum selects which of the glslshadermodeinfo entries should be used
3411 typedef enum shadermode_e
3412 {
3413         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3414         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3415         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3416         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3417         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3418         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3419         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3420         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3421         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3422         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3423         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3424         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3425         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3426         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3427         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3428         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3429         SHADERMODE_COUNT
3430 }
3431 shadermode_t;
3432
3433 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3434 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3435 {
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3438         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3448         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3451         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3452 };
3453
3454 #ifdef SUPPORTCG
3455 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3456 {
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3467         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3468         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3469         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3470         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3471         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3472         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3473 };
3474 #endif
3475
3476 #ifdef SUPPORTD3D
3477 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3478 {
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3494         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3495 };
3496 #endif
3497
3498 struct r_glsl_permutation_s;
3499 typedef struct r_glsl_permutation_s
3500 {
3501         /// hash lookup data
3502         struct r_glsl_permutation_s *hashnext;
3503         unsigned int mode;
3504         unsigned int permutation;
3505
3506         /// indicates if we have tried compiling this permutation already
3507         qboolean compiled;
3508         /// 0 if compilation failed
3509         int program;
3510         /// locations of detected uniforms in program object, or -1 if not found
3511         int loc_Texture_First;
3512         int loc_Texture_Second;
3513         int loc_Texture_GammaRamps;
3514         int loc_Texture_Normal;
3515         int loc_Texture_Color;
3516         int loc_Texture_Gloss;
3517         int loc_Texture_Glow;
3518         int loc_Texture_SecondaryNormal;
3519         int loc_Texture_SecondaryColor;
3520         int loc_Texture_SecondaryGloss;
3521         int loc_Texture_SecondaryGlow;
3522         int loc_Texture_Pants;
3523         int loc_Texture_Shirt;
3524         int loc_Texture_FogHeightTexture;
3525         int loc_Texture_FogMask;
3526         int loc_Texture_Lightmap;
3527         int loc_Texture_Deluxemap;
3528         int loc_Texture_Attenuation;
3529         int loc_Texture_Cube;
3530         int loc_Texture_Refraction;
3531         int loc_Texture_Reflection;
3532         int loc_Texture_ShadowMap2D;
3533         int loc_Texture_CubeProjection;
3534         int loc_Texture_ScreenDepth;
3535         int loc_Texture_ScreenNormalMap;
3536         int loc_Texture_ScreenDiffuse;
3537         int loc_Texture_ScreenSpecular;
3538         int loc_Texture_ReflectMask;
3539         int loc_Texture_ReflectCube;
3540         int loc_Alpha;
3541         int loc_BloomBlur_Parameters;
3542         int loc_ClientTime;
3543         int loc_Color_Ambient;
3544         int loc_Color_Diffuse;
3545         int loc_Color_Specular;
3546         int loc_Color_Glow;
3547         int loc_Color_Pants;
3548         int loc_Color_Shirt;
3549         int loc_DeferredColor_Ambient;
3550         int loc_DeferredColor_Diffuse;
3551         int loc_DeferredColor_Specular;
3552         int loc_DeferredMod_Diffuse;
3553         int loc_DeferredMod_Specular;
3554         int loc_DistortScaleRefractReflect;
3555         int loc_EyePosition;
3556         int loc_FogColor;
3557         int loc_FogHeightFade;
3558         int loc_FogPlane;
3559         int loc_FogPlaneViewDist;
3560         int loc_FogRangeRecip;
3561         int loc_LightColor;
3562         int loc_LightDir;
3563         int loc_LightPosition;
3564         int loc_OffsetMapping_Scale;
3565         int loc_PixelSize;
3566         int loc_ReflectColor;
3567         int loc_ReflectFactor;
3568         int loc_ReflectOffset;
3569         int loc_RefractColor;
3570         int loc_Saturation;
3571         int loc_ScreenCenterRefractReflect;
3572         int loc_ScreenScaleRefractReflect;
3573         int loc_ScreenToDepth;
3574         int loc_ShadowMap_Parameters;
3575         int loc_ShadowMap_TextureScale;
3576         int loc_SpecularPower;
3577         int loc_UserVec1;
3578         int loc_UserVec2;
3579         int loc_UserVec3;
3580         int loc_UserVec4;
3581         int loc_ViewTintColor;
3582         int loc_ViewToLight;
3583         int loc_ModelToLight;
3584         int loc_TexMatrix;
3585         int loc_BackgroundTexMatrix;
3586         int loc_ModelViewProjectionMatrix;
3587         int loc_ModelViewMatrix;
3588         int loc_PixelToScreenTexCoord;
3589         int loc_ModelToReflectCube;
3590         int loc_ShadowMapMatrix;
3591         int loc_BloomColorSubtract;
3592         int loc_NormalmapScrollBlend;
3593 }
3594 r_glsl_permutation_t;
3595
3596 #define SHADERPERMUTATION_HASHSIZE 256
3597
3598
3599 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3600 // these can NOT degrade! only use for simple stuff
3601 enum
3602 {
3603         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3604         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3605         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3606         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3607         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3608         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3609 };
3610 #define SHADERSTATICPARMS_COUNT 6
3611
3612 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3613 static int shaderstaticparms_count = 0;
3614
3615 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3616 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3617 qboolean R_CompileShader_CheckStaticParms(void)
3618 {
3619         static int r_compileshader_staticparms_save[1];
3620         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3621         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3622
3623         // detect all
3624         if (r_glsl_saturation_redcompensate.integer)
3625                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3626         if (r_shadow_glossexact.integer)
3627                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3628         if (r_glsl_postprocess.integer)
3629         {
3630                 if (r_glsl_postprocess_uservec1_enable.integer)
3631                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3632                 if (r_glsl_postprocess_uservec2_enable.integer)
3633                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3634                 if (r_glsl_postprocess_uservec3_enable.integer)
3635                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3636                 if (r_glsl_postprocess_uservec4_enable.integer)
3637                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3638         }
3639         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3640 }
3641
3642 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3643         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3644                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3645         else \
3646                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3647 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3648 {
3649         shaderstaticparms_count = 0;
3650
3651         // emit all
3652         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3653         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3654         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3655         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3656         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3657         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3658 }
3659
3660 /// information about each possible shader permutation
3661 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3662 /// currently selected permutation
3663 r_glsl_permutation_t *r_glsl_permutation;
3664 /// storage for permutations linked in the hash table
3665 memexpandablearray_t r_glsl_permutationarray;
3666
3667 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3668 {
3669         //unsigned int hashdepth = 0;
3670         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3671         r_glsl_permutation_t *p;
3672         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3673         {
3674                 if (p->mode == mode && p->permutation == permutation)
3675                 {
3676                         //if (hashdepth > 10)
3677                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3678                         return p;
3679                 }
3680                 //hashdepth++;
3681         }
3682         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3683         p->mode = mode;
3684         p->permutation = permutation;
3685         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3686         r_glsl_permutationhash[mode][hashindex] = p;
3687         //if (hashdepth > 10)
3688         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3689         return p;
3690 }
3691
3692 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3693 {
3694         char *shaderstring;
3695         if (!filename || !filename[0])
3696                 return NULL;
3697         if (!strcmp(filename, "glsl/default.glsl"))
3698         {
3699                 if (!glslshaderstring)
3700                 {
3701                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3702                         if (glslshaderstring)
3703                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3704                         else
3705                                 glslshaderstring = (char *)builtinshaderstring;
3706                 }
3707                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3708                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3709                 return shaderstring;
3710         }
3711         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3712         if (shaderstring)
3713         {
3714                 if (printfromdisknotice)
3715                         Con_DPrintf("from disk %s... ", filename);
3716                 return shaderstring;
3717         }
3718         return shaderstring;
3719 }
3720
3721 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3722 {
3723         int i;
3724         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3725         char *vertexstring, *geometrystring, *fragmentstring;
3726         char permutationname[256];
3727         int vertstrings_count = 0;
3728         int geomstrings_count = 0;
3729         int fragstrings_count = 0;
3730         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3731         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3733
3734         if (p->compiled)
3735                 return;
3736         p->compiled = true;
3737         p->program = 0;
3738
3739         permutationname[0] = 0;
3740         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3741         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3742         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3743
3744         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3745
3746         // the first pretext is which type of shader to compile as
3747         // (later these will all be bound together as a program object)
3748         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3749         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3750         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3751
3752         // the second pretext is the mode (for example a light source)
3753         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3754         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3755         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3756         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3757
3758         // now add all the permutation pretexts
3759         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3760         {
3761                 if (permutation & (1<<i))
3762                 {
3763                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3764                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3765                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3766                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3767                 }
3768                 else
3769                 {
3770                         // keep line numbers correct
3771                         vertstrings_list[vertstrings_count++] = "\n";
3772                         geomstrings_list[geomstrings_count++] = "\n";
3773                         fragstrings_list[fragstrings_count++] = "\n";
3774                 }
3775         }
3776
3777         // add static parms
3778         R_CompileShader_AddStaticParms(mode, permutation);
3779         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3780         vertstrings_count += shaderstaticparms_count;
3781         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3782         geomstrings_count += shaderstaticparms_count;
3783         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3784         fragstrings_count += shaderstaticparms_count;
3785
3786         // now append the shader text itself
3787         vertstrings_list[vertstrings_count++] = vertexstring;
3788         geomstrings_list[geomstrings_count++] = geometrystring;
3789         fragstrings_list[fragstrings_count++] = fragmentstring;
3790
3791         // if any sources were NULL, clear the respective list
3792         if (!vertexstring)
3793                 vertstrings_count = 0;
3794         if (!geometrystring)
3795                 geomstrings_count = 0;
3796         if (!fragmentstring)
3797                 fragstrings_count = 0;
3798
3799         // compile the shader program
3800         if (vertstrings_count + geomstrings_count + fragstrings_count)
3801                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3802         if (p->program)
3803         {
3804                 CHECKGLERROR
3805                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3806                 // look up all the uniform variable names we care about, so we don't
3807                 // have to look them up every time we set them
3808
3809                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3810                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3811                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3812                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3813                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3814                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3815                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3816                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3817                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3818                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3819                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3820                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3821                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3822                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3823                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3824                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3825                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3826                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3827                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3828                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3829                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3830                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3831                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3832                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3833                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3834                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3835                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3836                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3837                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3838                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3839                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3840                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3841                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3842                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3843                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3844                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3845                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3846                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3847                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3848                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3849                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3850                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3851                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3852                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3853                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3854                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3855                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3856                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3857                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3858                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3859                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3860                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3861                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3862                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3863                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3864                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3865                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3866                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3867                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3868                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3869                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3870                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3871                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3872                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3873                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3874                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3875                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3876                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3877                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3878                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3879                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3880                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3881                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3882                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3883                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3884                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3885                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3886                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3887                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3888                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3889                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3890                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3891                 // initialize the samplers to refer to the texture units we use
3892                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3893                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3894                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3895                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3896                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3897                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3898                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3899                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3900                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3901                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3902                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3903                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3904                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3905                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3906                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3907                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3908                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3909                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3910                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3911                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3912                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3913                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3914                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3915                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3916                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3917                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3918                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3919                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3920                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3921                 CHECKGLERROR
3922                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3923         }
3924         else
3925                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3926
3927         // free the strings
3928         if (vertexstring)
3929                 Mem_Free(vertexstring);
3930         if (geometrystring)
3931                 Mem_Free(geometrystring);
3932         if (fragmentstring)
3933                 Mem_Free(fragmentstring);
3934 }
3935
3936 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3937 {
3938         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3939         if (r_glsl_permutation != perm)
3940         {
3941                 r_glsl_permutation = perm;
3942                 if (!r_glsl_permutation->program)
3943                 {
3944                         if (!r_glsl_permutation->compiled)
3945                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3946                         if (!r_glsl_permutation->program)
3947                         {
3948                                 // remove features until we find a valid permutation
3949                                 int i;
3950                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3951                                 {
3952                                         // reduce i more quickly whenever it would not remove any bits
3953                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3954                                         if (!(permutation & j))
3955                                                 continue;
3956                                         permutation -= j;
3957                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3958                                         if (!r_glsl_permutation->compiled)
3959                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3960                                         if (r_glsl_permutation->program)
3961                                                 break;
3962                                 }
3963                                 if (i >= SHADERPERMUTATION_COUNT)
3964                                 {
3965                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3966                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3967                                         qglUseProgramObjectARB(0);CHECKGLERROR
3968                                         return; // no bit left to clear, entire mode is broken
3969                                 }
3970                         }
3971                 }
3972                 CHECKGLERROR
3973                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3974         }
3975         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3976         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3977         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3978 }
3979
3980 #ifdef SUPPORTCG
3981 #include <Cg/cgGL.h>
3982 struct r_cg_permutation_s;
3983 typedef struct r_cg_permutation_s
3984 {
3985         /// hash lookup data
3986         struct r_cg_permutation_s *hashnext;
3987         unsigned int mode;
3988         unsigned int permutation;
3989
3990         /// indicates if we have tried compiling this permutation already
3991         qboolean compiled;
3992         /// 0 if compilation failed
3993         CGprogram vprogram;
3994         CGprogram fprogram;
3995         /// locations of detected parameters in programs, or NULL if not found
3996         CGparameter vp_EyePosition;
3997         CGparameter vp_FogPlane;
3998         CGparameter vp_LightDir;
3999         CGparameter vp_LightPosition;
4000         CGparameter vp_ModelToLight;
4001         CGparameter vp_TexMatrix;
4002         CGparameter vp_BackgroundTexMatrix;
4003         CGparameter vp_ModelViewProjectionMatrix;
4004         CGparameter vp_ModelViewMatrix;
4005         CGparameter vp_ShadowMapMatrix;
4006
4007         CGparameter fp_Texture_First;
4008         CGparameter fp_Texture_Second;
4009         CGparameter fp_Texture_GammaRamps;
4010         CGparameter fp_Texture_Normal;
4011         CGparameter fp_Texture_Color;
4012         CGparameter fp_Texture_Gloss;
4013         CGparameter fp_Texture_Glow;
4014         CGparameter fp_Texture_SecondaryNormal;
4015         CGparameter fp_Texture_SecondaryColor;
4016         CGparameter fp_Texture_SecondaryGloss;
4017         CGparameter fp_Texture_SecondaryGlow;
4018         CGparameter fp_Texture_Pants;
4019         CGparameter fp_Texture_Shirt;
4020         CGparameter fp_Texture_FogHeightTexture;
4021         CGparameter fp_Texture_FogMask;
4022         CGparameter fp_Texture_Lightmap;
4023         CGparameter fp_Texture_Deluxemap;
4024         CGparameter fp_Texture_Attenuation;
4025         CGparameter fp_Texture_Cube;
4026         CGparameter fp_Texture_Refraction;
4027         CGparameter fp_Texture_Reflection;
4028         CGparameter fp_Texture_ShadowMap2D;
4029         CGparameter fp_Texture_CubeProjection;
4030         CGparameter fp_Texture_ScreenDepth;
4031         CGparameter fp_Texture_ScreenNormalMap;
4032         CGparameter fp_Texture_ScreenDiffuse;
4033         CGparameter fp_Texture_ScreenSpecular;
4034         CGparameter fp_Texture_ReflectMask;
4035         CGparameter fp_Texture_ReflectCube;
4036         CGparameter fp_Alpha;
4037         CGparameter fp_BloomBlur_Parameters;
4038         CGparameter fp_ClientTime;
4039         CGparameter fp_Color_Ambient;
4040         CGparameter fp_Color_Diffuse;
4041         CGparameter fp_Color_Specular;
4042         CGparameter fp_Color_Glow;
4043         CGparameter fp_Color_Pants;
4044         CGparameter fp_Color_Shirt;
4045         CGparameter fp_DeferredColor_Ambient;
4046         CGparameter fp_DeferredColor_Diffuse;
4047         CGparameter fp_DeferredColor_Specular;
4048         CGparameter fp_DeferredMod_Diffuse;
4049         CGparameter fp_DeferredMod_Specular;
4050         CGparameter fp_DistortScaleRefractReflect;
4051         CGparameter fp_EyePosition;
4052         CGparameter fp_FogColor;
4053         CGparameter fp_FogHeightFade;
4054         CGparameter fp_FogPlane;
4055         CGparameter fp_FogPlaneViewDist;
4056         CGparameter fp_FogRangeRecip;
4057         CGparameter fp_LightColor;
4058         CGparameter fp_LightDir;
4059         CGparameter fp_LightPosition;
4060         CGparameter fp_OffsetMapping_Scale;
4061         CGparameter fp_PixelSize;
4062         CGparameter fp_ReflectColor;
4063         CGparameter fp_ReflectFactor;
4064         CGparameter fp_ReflectOffset;
4065         CGparameter fp_RefractColor;
4066         CGparameter fp_Saturation;
4067         CGparameter fp_ScreenCenterRefractReflect;
4068         CGparameter fp_ScreenScaleRefractReflect;
4069         CGparameter fp_ScreenToDepth;
4070         CGparameter fp_ShadowMap_Parameters;
4071         CGparameter fp_ShadowMap_TextureScale;
4072         CGparameter fp_SpecularPower;
4073         CGparameter fp_UserVec1;
4074         CGparameter fp_UserVec2;
4075         CGparameter fp_UserVec3;
4076         CGparameter fp_UserVec4;
4077         CGparameter fp_ViewTintColor;
4078         CGparameter fp_ViewToLight;
4079         CGparameter fp_PixelToScreenTexCoord;
4080         CGparameter fp_ModelToReflectCube;
4081         CGparameter fp_BloomColorSubtract;
4082         CGparameter fp_NormalmapScrollBlend;
4083 }
4084 r_cg_permutation_t;
4085
4086 /// information about each possible shader permutation
4087 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4088 /// currently selected permutation
4089 r_cg_permutation_t *r_cg_permutation;
4090 /// storage for permutations linked in the hash table
4091 memexpandablearray_t r_cg_permutationarray;
4092
4093 #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));}}
4094
4095 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4096 {
4097         //unsigned int hashdepth = 0;
4098         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4099         r_cg_permutation_t *p;
4100         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4101         {
4102                 if (p->mode == mode && p->permutation == permutation)
4103                 {
4104                         //if (hashdepth > 10)
4105                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4106                         return p;
4107                 }
4108                 //hashdepth++;
4109         }
4110         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4111         p->mode = mode;
4112         p->permutation = permutation;
4113         p->hashnext = r_cg_permutationhash[mode][hashindex];
4114         r_cg_permutationhash[mode][hashindex] = p;
4115         //if (hashdepth > 10)
4116         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4117         return p;
4118 }
4119
4120 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4121 {
4122         char *shaderstring;
4123         if (!filename || !filename[0])
4124                 return NULL;
4125         if (!strcmp(filename, "cg/default.cg"))
4126         {
4127                 if (!cgshaderstring)
4128                 {
4129                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4130                         if (cgshaderstring)
4131                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4132                         else
4133                                 cgshaderstring = (char *)builtincgshaderstring;
4134                 }
4135                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4136                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4137                 return shaderstring;
4138         }
4139         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4140         if (shaderstring)
4141         {
4142                 if (printfromdisknotice)
4143                         Con_DPrintf("from disk %s... ", filename);
4144                 return shaderstring;
4145         }
4146         return shaderstring;
4147 }
4148
4149 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4150 {
4151         // TODO: load or create .fp and .vp shader files
4152 }
4153
4154 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4155 {
4156         int i;
4157         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4158         int vertstring_length = 0;
4159         int geomstring_length = 0;
4160         int fragstring_length = 0;
4161         char *t;
4162         char *vertexstring, *geometrystring, *fragmentstring;
4163         char *vertstring, *geomstring, *fragstring;
4164         char permutationname[256];
4165         char cachename[256];
4166         CGprofile vertexProfile;
4167         CGprofile fragmentProfile;
4168         int vertstrings_count = 0;
4169         int geomstrings_count = 0;
4170         int fragstrings_count = 0;
4171         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4172         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4174
4175         if (p->compiled)
4176                 return;
4177         p->compiled = true;
4178         p->vprogram = NULL;
4179         p->fprogram = NULL;
4180
4181         permutationname[0] = 0;
4182         cachename[0] = 0;
4183         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4184         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4185         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4186
4187         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4188         strlcat(cachename, "cg/", sizeof(cachename));
4189
4190         // the first pretext is which type of shader to compile as
4191         // (later these will all be bound together as a program object)
4192         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4193         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4194         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4195
4196         // the second pretext is the mode (for example a light source)
4197         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4198         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4199         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4200         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4201         strlcat(cachename, modeinfo->name, sizeof(cachename));
4202
4203         // now add all the permutation pretexts
4204         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4205         {
4206                 if (permutation & (1<<i))
4207                 {
4208                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4209                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4211                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4212                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4213                 }
4214                 else
4215                 {
4216                         // keep line numbers correct
4217                         vertstrings_list[vertstrings_count++] = "\n";
4218                         geomstrings_list[geomstrings_count++] = "\n";
4219                         fragstrings_list[fragstrings_count++] = "\n";
4220                 }
4221         }
4222
4223         // add static parms
4224         R_CompileShader_AddStaticParms(mode, permutation);
4225         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4226         vertstrings_count += shaderstaticparms_count;
4227         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4228         geomstrings_count += shaderstaticparms_count;
4229         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4230         fragstrings_count += shaderstaticparms_count;
4231
4232         // replace spaces in the cachename with _ characters
4233         for (i = 0;cachename[i];i++)
4234                 if (cachename[i] == ' ')
4235                         cachename[i] = '_';
4236
4237         // now append the shader text itself
4238         vertstrings_list[vertstrings_count++] = vertexstring;
4239         geomstrings_list[geomstrings_count++] = geometrystring;
4240         fragstrings_list[fragstrings_count++] = fragmentstring;
4241
4242         // if any sources were NULL, clear the respective list
4243         if (!vertexstring)
4244                 vertstrings_count = 0;
4245         if (!geometrystring)
4246                 geomstrings_count = 0;
4247         if (!fragmentstring)
4248                 fragstrings_count = 0;
4249
4250         vertstring_length = 0;
4251         for (i = 0;i < vertstrings_count;i++)
4252                 vertstring_length += strlen(vertstrings_list[i]);
4253         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4254         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4255                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4256
4257         geomstring_length = 0;
4258         for (i = 0;i < geomstrings_count;i++)
4259                 geomstring_length += strlen(geomstrings_list[i]);
4260         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4261         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4262                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4263
4264         fragstring_length = 0;
4265         for (i = 0;i < fragstrings_count;i++)
4266                 fragstring_length += strlen(fragstrings_list[i]);
4267         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4268         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4269                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4270
4271         CHECKGLERROR
4272         CHECKCGERROR
4273         //vertexProfile = CG_PROFILE_ARBVP1;
4274         //fragmentProfile = CG_PROFILE_ARBFP1;
4275         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4276         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4277         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4278         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4279         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4280         CHECKGLERROR
4281
4282         // try to load the cached shader, or generate one
4283         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4284
4285         // if caching failed, do a dynamic compile for now
4286         CHECKCGERROR
4287         if (vertstring[0] && !p->vprogram)
4288                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4289         CHECKCGERROR
4290         if (fragstring[0] && !p->fprogram)
4291                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4292         CHECKCGERROR
4293
4294         // look up all the uniform variable names we care about, so we don't
4295         // have to look them up every time we set them
4296         if (p->vprogram)
4297         {
4298                 CHECKCGERROR
4299                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4300                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4301                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4302                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4303                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4304                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4305                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4306                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4307                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4308                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4309                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4310                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4311                 CHECKCGERROR
4312         }
4313         if (p->fprogram)
4314         {
4315                 CHECKCGERROR
4316                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4317                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4318                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4319                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4320                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4321                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4322                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4323                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4324                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4325                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4326                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4327                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4328                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4329                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4330                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4331                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4332                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4333                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4334                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4335                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4336                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4337                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4338                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4339                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4340                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4341                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4342                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4343                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4344                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4345                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4346                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4347                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4348                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4349                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4350                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4351                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4352                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4353                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4354                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4355                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4356                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4357                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4358                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4359                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4360                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4361                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4362                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4363                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4364                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4365                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4366                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4367                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4368                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4369                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4370                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4371                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4372                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4373                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4374                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4375                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4376                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4377                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4378                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4379                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4380                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4381                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4382                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4383                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4384                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4385                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4386                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4387                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4388                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4389                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4390                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4391                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4392                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4393                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4394                 CHECKCGERROR
4395         }
4396
4397         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4398                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4399         else
4400                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4401
4402         // free the strings
4403         if (vertstring)
4404                 Mem_Free(vertstring);
4405         if (geomstring)
4406                 Mem_Free(geomstring);
4407         if (fragstring)
4408                 Mem_Free(fragstring);
4409         if (vertexstring)
4410                 Mem_Free(vertexstring);
4411         if (geometrystring)
4412                 Mem_Free(geometrystring);
4413         if (fragmentstring)
4414                 Mem_Free(fragmentstring);
4415 }
4416
4417 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4418 {
4419         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4420         CHECKGLERROR
4421         CHECKCGERROR
4422         if (r_cg_permutation != perm)
4423         {
4424                 r_cg_permutation = perm;
4425                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4426                 {
4427                         if (!r_cg_permutation->compiled)
4428                                 R_CG_CompilePermutation(perm, mode, permutation);
4429                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4430                         {
4431                                 // remove features until we find a valid permutation
4432                                 int i;
4433                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4434                                 {
4435                                         // reduce i more quickly whenever it would not remove any bits
4436                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4437                                         if (!(permutation & j))
4438                                                 continue;
4439                                         permutation -= j;
4440                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4441                                         if (!r_cg_permutation->compiled)
4442                                                 R_CG_CompilePermutation(perm, mode, permutation);
4443                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4444                                                 break;
4445                                 }
4446                                 if (i >= SHADERPERMUTATION_COUNT)
4447                                 {
4448                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4449                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4450                                         return; // no bit left to clear, entire mode is broken
4451                                 }
4452                         }
4453                 }
4454                 CHECKGLERROR
4455                 CHECKCGERROR
4456                 if (r_cg_permutation->vprogram)
4457                 {
4458                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4459                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4460                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4461                 }
4462                 else
4463                 {
4464                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4465                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466                 }
4467                 if (r_cg_permutation->fprogram)
4468                 {
4469                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4470                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4471                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4472                 }
4473                 else
4474                 {
4475                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4476                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4477                 }
4478         }
4479         CHECKCGERROR
4480         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4481         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4482         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4483 }
4484
4485 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4486 {
4487         cgGLSetTextureParameter(param, R_GetTexture(tex));
4488         cgGLEnableTextureParameter(param);
4489 }
4490 #endif
4491
4492 #ifdef SUPPORTD3D
4493
4494 #ifdef SUPPORTD3D
4495 #include <d3d9.h>
4496 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4497 extern D3DCAPS9 vid_d3d9caps;
4498 #endif
4499
4500 struct r_hlsl_permutation_s;
4501 typedef struct r_hlsl_permutation_s
4502 {
4503         /// hash lookup data
4504         struct r_hlsl_permutation_s *hashnext;
4505         unsigned int mode;
4506         unsigned int permutation;
4507
4508         /// indicates if we have tried compiling this permutation already
4509         qboolean compiled;
4510         /// NULL if compilation failed
4511         IDirect3DVertexShader9 *vertexshader;
4512         IDirect3DPixelShader9 *pixelshader;
4513 }
4514 r_hlsl_permutation_t;
4515
4516 typedef enum D3DVSREGISTER_e
4517 {
4518         D3DVSREGISTER_TexMatrix = 0, // float4x4
4519         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4520         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4521         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4522         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4523         D3DVSREGISTER_ModelToLight = 20, // float4x4
4524         D3DVSREGISTER_EyePosition = 24,
4525         D3DVSREGISTER_FogPlane = 25,
4526         D3DVSREGISTER_LightDir = 26,
4527         D3DVSREGISTER_LightPosition = 27,
4528 }
4529 D3DVSREGISTER_t;
4530
4531 typedef enum D3DPSREGISTER_e
4532 {
4533         D3DPSREGISTER_Alpha = 0,
4534         D3DPSREGISTER_BloomBlur_Parameters = 1,
4535         D3DPSREGISTER_ClientTime = 2,
4536         D3DPSREGISTER_Color_Ambient = 3,
4537         D3DPSREGISTER_Color_Diffuse = 4,
4538         D3DPSREGISTER_Color_Specular = 5,
4539         D3DPSREGISTER_Color_Glow = 6,
4540         D3DPSREGISTER_Color_Pants = 7,
4541         D3DPSREGISTER_Color_Shirt = 8,
4542         D3DPSREGISTER_DeferredColor_Ambient = 9,
4543         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4544         D3DPSREGISTER_DeferredColor_Specular = 11,
4545         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4546         D3DPSREGISTER_DeferredMod_Specular = 13,
4547         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4548         D3DPSREGISTER_EyePosition = 15, // unused
4549         D3DPSREGISTER_FogColor = 16,
4550         D3DPSREGISTER_FogHeightFade = 17,
4551         D3DPSREGISTER_FogPlane = 18,
4552         D3DPSREGISTER_FogPlaneViewDist = 19,
4553         D3DPSREGISTER_FogRangeRecip = 20,
4554         D3DPSREGISTER_LightColor = 21,
4555         D3DPSREGISTER_LightDir = 22, // unused
4556         D3DPSREGISTER_LightPosition = 23,
4557         D3DPSREGISTER_OffsetMapping_Scale = 24,
4558         D3DPSREGISTER_PixelSize = 25,
4559         D3DPSREGISTER_ReflectColor = 26,
4560         D3DPSREGISTER_ReflectFactor = 27,
4561         D3DPSREGISTER_ReflectOffset = 28,
4562         D3DPSREGISTER_RefractColor = 29,
4563         D3DPSREGISTER_Saturation = 30,
4564         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4565         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4566         D3DPSREGISTER_ScreenToDepth = 33,
4567         D3DPSREGISTER_ShadowMap_Parameters = 34,
4568         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4569         D3DPSREGISTER_SpecularPower = 36,
4570         D3DPSREGISTER_UserVec1 = 37,
4571         D3DPSREGISTER_UserVec2 = 38,
4572         D3DPSREGISTER_UserVec3 = 39,
4573         D3DPSREGISTER_UserVec4 = 40,
4574         D3DPSREGISTER_ViewTintColor = 41,
4575         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4576         D3DPSREGISTER_BloomColorSubtract = 43,
4577         D3DPSREGISTER_ViewToLight = 44, // float4x4
4578         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4579         D3DPSREGISTER_NormalmapScrollBlend = 52,
4580         // next at 53
4581 }
4582 D3DPSREGISTER_t;
4583
4584 /// information about each possible shader permutation
4585 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4586 /// currently selected permutation
4587 r_hlsl_permutation_t *r_hlsl_permutation;
4588 /// storage for permutations linked in the hash table
4589 memexpandablearray_t r_hlsl_permutationarray;
4590
4591 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4592 {
4593         //unsigned int hashdepth = 0;
4594         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4595         r_hlsl_permutation_t *p;
4596         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4597         {
4598                 if (p->mode == mode && p->permutation == permutation)
4599                 {
4600                         //if (hashdepth > 10)
4601                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4602                         return p;
4603                 }
4604                 //hashdepth++;
4605         }
4606         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4607         p->mode = mode;
4608         p->permutation = permutation;
4609         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4610         r_hlsl_permutationhash[mode][hashindex] = p;
4611         //if (hashdepth > 10)
4612         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4613         return p;
4614 }
4615
4616 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4617 {
4618         char *shaderstring;
4619         if (!filename || !filename[0])
4620                 return NULL;
4621         if (!strcmp(filename, "hlsl/default.hlsl"))
4622         {
4623                 if (!hlslshaderstring)
4624                 {
4625                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4626                         if (hlslshaderstring)
4627                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4628                         else
4629                                 hlslshaderstring = (char *)builtincgshaderstring;
4630                 }
4631                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4632                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4633                 return shaderstring;
4634         }
4635         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4636         if (shaderstring)
4637         {
4638                 if (printfromdisknotice)
4639                         Con_DPrintf("from disk %s... ", filename);
4640                 return shaderstring;
4641         }
4642         return shaderstring;
4643 }
4644
4645 #include <d3dx9.h>
4646 //#include <d3dx9shader.h>
4647 //#include <d3dx9mesh.h>
4648
4649 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4650 {
4651         DWORD *vsbin = NULL;
4652         DWORD *psbin = NULL;
4653         fs_offset_t vsbinsize;
4654         fs_offset_t psbinsize;
4655 //      IDirect3DVertexShader9 *vs = NULL;
4656 //      IDirect3DPixelShader9 *ps = NULL;
4657         ID3DXBuffer *vslog = NULL;
4658         ID3DXBuffer *vsbuffer = NULL;
4659         ID3DXConstantTable *vsconstanttable = NULL;
4660         ID3DXBuffer *pslog = NULL;
4661         ID3DXBuffer *psbuffer = NULL;
4662         ID3DXConstantTable *psconstanttable = NULL;
4663         int vsresult = 0;
4664         int psresult = 0;
4665         char temp[MAX_INPUTLINE];
4666         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4667         qboolean debugshader = gl_paranoid.integer != 0;
4668         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4669         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4670         if (!debugshader)
4671         {
4672                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4673                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4674         }
4675         if ((!vsbin && vertstring) || (!psbin && fragstring))
4676         {
4677                 const char* dllnames_d3dx9 [] =
4678                 {
4679                         "d3dx9_43.dll",
4680                         "d3dx9_42.dll",
4681                         "d3dx9_41.dll",
4682                         "d3dx9_40.dll",
4683                         "d3dx9_39.dll",
4684                         "d3dx9_38.dll",
4685                         "d3dx9_37.dll",
4686                         "d3dx9_36.dll",
4687                         "d3dx9_35.dll",
4688                         "d3dx9_34.dll",
4689                         "d3dx9_33.dll",
4690                         "d3dx9_32.dll",
4691                         "d3dx9_31.dll",
4692                         "d3dx9_30.dll",
4693                         "d3dx9_29.dll",
4694                         "d3dx9_28.dll",
4695                         "d3dx9_27.dll",
4696                         "d3dx9_26.dll",
4697                         "d3dx9_25.dll",
4698                         "d3dx9_24.dll",
4699                         NULL
4700                 };
4701                 dllhandle_t d3dx9_dll = NULL;
4702                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4703                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4704                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4705                 dllfunction_t d3dx9_dllfuncs[] =
4706                 {
4707                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4708                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4709                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4710                         {NULL, NULL}
4711                 };
4712                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4713                 {
4714                         DWORD shaderflags = 0;
4715                         if (debugshader)
4716                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4717                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4718                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4719                         if (vertstring && vertstring[0])
4720                         {
4721                                 if (debugshader)
4722                                 {
4723 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4724 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4725                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4726                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4727                                 }
4728                                 else
4729                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4730                                 if (vsbuffer)
4731                                 {
4732                                         vsbinsize = vsbuffer->GetBufferSize();
4733                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4734                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4735                                         vsbuffer->Release();
4736                                 }
4737                                 if (vslog)
4738                                 {
4739                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4740                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4741                                         vslog->Release();
4742                                 }
4743                         }
4744                         if (fragstring && fragstring[0])
4745                         {
4746                                 if (debugshader)
4747                                 {
4748 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4749 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4750                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4751                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4752                                 }
4753                                 else
4754                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4755                                 if (psbuffer)
4756                                 {
4757                                         psbinsize = psbuffer->GetBufferSize();
4758                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4759                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4760                                         psbuffer->Release();
4761                                 }
4762                                 if (pslog)
4763                                 {
4764                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4765                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4766                                         pslog->Release();
4767                                 }
4768                         }
4769                         Sys_UnloadLibrary(&d3dx9_dll);
4770                 }
4771                 else
4772                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4773         }
4774         if (vsbin && psbin)
4775         {
4776                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4777                 if (FAILED(vsresult))
4778                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4779                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4780                 if (FAILED(psresult))
4781                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4782         }
4783         // free the shader data
4784         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4785         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4786 }
4787
4788 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4789 {
4790         int i;
4791         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4792         int vertstring_length = 0;
4793         int geomstring_length = 0;
4794         int fragstring_length = 0;
4795         char *t;
4796         char *vertexstring, *geometrystring, *fragmentstring;
4797         char *vertstring, *geomstring, *fragstring;
4798         char permutationname[256];
4799         char cachename[256];
4800         int vertstrings_count = 0;
4801         int geomstrings_count = 0;
4802         int fragstrings_count = 0;
4803         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4804         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4806
4807         if (p->compiled)
4808                 return;
4809         p->compiled = true;
4810         p->vertexshader = NULL;
4811         p->pixelshader = NULL;
4812
4813         permutationname[0] = 0;
4814         cachename[0] = 0;
4815         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4816         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4817         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4818
4819         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4820         strlcat(cachename, "hlsl/", sizeof(cachename));
4821
4822         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4823         vertstrings_count = 0;
4824         geomstrings_count = 0;
4825         fragstrings_count = 0;
4826         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4827         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4828         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4829
4830         // the first pretext is which type of shader to compile as
4831         // (later these will all be bound together as a program object)
4832         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4833         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4834         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4835
4836         // the second pretext is the mode (for example a light source)
4837         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4838         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4839         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4840         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4841         strlcat(cachename, modeinfo->name, sizeof(cachename));
4842
4843         // now add all the permutation pretexts
4844         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4845         {
4846                 if (permutation & (1<<i))
4847                 {
4848                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4849                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4851                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4852                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4853                 }
4854                 else
4855                 {
4856                         // keep line numbers correct
4857                         vertstrings_list[vertstrings_count++] = "\n";
4858                         geomstrings_list[geomstrings_count++] = "\n";
4859                         fragstrings_list[fragstrings_count++] = "\n";
4860                 }
4861         }
4862
4863         // add static parms
4864         R_CompileShader_AddStaticParms(mode, permutation);
4865         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4866         vertstrings_count += shaderstaticparms_count;
4867         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4868         geomstrings_count += shaderstaticparms_count;
4869         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4870         fragstrings_count += shaderstaticparms_count;
4871
4872         // replace spaces in the cachename with _ characters
4873         for (i = 0;cachename[i];i++)
4874                 if (cachename[i] == ' ')
4875                         cachename[i] = '_';
4876
4877         // now append the shader text itself
4878         vertstrings_list[vertstrings_count++] = vertexstring;
4879         geomstrings_list[geomstrings_count++] = geometrystring;
4880         fragstrings_list[fragstrings_count++] = fragmentstring;
4881
4882         // if any sources were NULL, clear the respective list
4883         if (!vertexstring)
4884                 vertstrings_count = 0;
4885         if (!geometrystring)
4886                 geomstrings_count = 0;
4887         if (!fragmentstring)
4888                 fragstrings_count = 0;
4889
4890         vertstring_length = 0;
4891         for (i = 0;i < vertstrings_count;i++)
4892                 vertstring_length += strlen(vertstrings_list[i]);
4893         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4894         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4895                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4896
4897         geomstring_length = 0;
4898         for (i = 0;i < geomstrings_count;i++)
4899                 geomstring_length += strlen(geomstrings_list[i]);
4900         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4901         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4902                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4903
4904         fragstring_length = 0;
4905         for (i = 0;i < fragstrings_count;i++)
4906                 fragstring_length += strlen(fragstrings_list[i]);
4907         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4908         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4909                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4910
4911         // try to load the cached shader, or generate one
4912         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4913
4914         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4915                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4916         else
4917                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4918
4919         // free the strings
4920         if (vertstring)
4921                 Mem_Free(vertstring);
4922         if (geomstring)
4923                 Mem_Free(geomstring);
4924         if (fragstring)
4925                 Mem_Free(fragstring);
4926         if (vertexstring)
4927                 Mem_Free(vertexstring);
4928         if (geometrystring)
4929                 Mem_Free(geometrystring);
4930         if (fragmentstring)
4931                 Mem_Free(fragmentstring);
4932 }
4933
4934 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4935 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4936 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);}
4937 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);}
4938 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);}
4939 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);}
4940
4941 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4942 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4943 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);}
4944 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);}
4945 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);}
4946 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);}
4947
4948 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4949 {
4950         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4951         if (r_hlsl_permutation != perm)
4952         {
4953                 r_hlsl_permutation = perm;
4954                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4955                 {
4956                         if (!r_hlsl_permutation->compiled)
4957                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4958                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4959                         {
4960                                 // remove features until we find a valid permutation
4961                                 int i;
4962                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4963                                 {
4964                                         // reduce i more quickly whenever it would not remove any bits
4965                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4966                                         if (!(permutation & j))
4967                                                 continue;
4968                                         permutation -= j;
4969                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4970                                         if (!r_hlsl_permutation->compiled)
4971                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4972                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4973                                                 break;
4974                                 }
4975                                 if (i >= SHADERPERMUTATION_COUNT)
4976                                 {
4977                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4978                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4979                                         return; // no bit left to clear, entire mode is broken
4980                                 }
4981                         }
4982                 }
4983                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4984                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4985         }
4986         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4987         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4988         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4989 }
4990 #endif
4991
4992 void R_GLSL_Restart_f(void)
4993 {
4994         unsigned int i, limit;
4995         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4996                 Mem_Free(glslshaderstring);
4997         glslshaderstring = NULL;
4998         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4999                 Mem_Free(cgshaderstring);
5000         cgshaderstring = NULL;
5001         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5002                 Mem_Free(hlslshaderstring);
5003         hlslshaderstring = NULL;
5004         switch(vid.renderpath)
5005         {
5006         case RENDERPATH_D3D9:
5007 #ifdef SUPPORTD3D
5008                 {
5009                         r_hlsl_permutation_t *p;
5010                         r_hlsl_permutation = NULL;
5011 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5016                         for (i = 0;i < limit;i++)
5017                         {
5018                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5019                                 {
5020                                         if (p->vertexshader)
5021                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5022                                         if (p->pixelshader)
5023                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5024                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5025                                 }
5026                         }
5027                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5028                 }
5029 #endif
5030                 break;
5031         case RENDERPATH_D3D10:
5032                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5033                 break;
5034         case RENDERPATH_D3D11:
5035                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5036                 break;
5037         case RENDERPATH_GL20:
5038                 {
5039                         r_glsl_permutation_t *p;
5040                         r_glsl_permutation = NULL;
5041                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5042                         for (i = 0;i < limit;i++)
5043                         {
5044                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5045                                 {
5046                                         GL_Backend_FreeProgram(p->program);
5047                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5048                                 }
5049                         }
5050                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5051                 }
5052                 break;
5053         case RENDERPATH_CGGL:
5054 #ifdef SUPPORTCG
5055                 {
5056                         r_cg_permutation_t *p;
5057                         r_cg_permutation = NULL;
5058                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5059                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5060                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5061                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5062                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5063                         for (i = 0;i < limit;i++)
5064                         {
5065                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5066                                 {
5067                                         if (p->vprogram)
5068                                                 cgDestroyProgram(p->vprogram);
5069                                         if (p->fprogram)
5070                                                 cgDestroyProgram(p->fprogram);
5071                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5072                                 }
5073                         }
5074                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5075                 }
5076 #endif
5077                 break;
5078         case RENDERPATH_GL13:
5079         case RENDERPATH_GL11:
5080                 break;
5081         }
5082 }
5083
5084 void R_GLSL_DumpShader_f(void)
5085 {
5086         int i;
5087         qfile_t *file;
5088
5089         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5090         if (file)
5091         {
5092                 FS_Print(file, "/* The engine may define the following macros:\n");
5093                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5094                 for (i = 0;i < SHADERMODE_COUNT;i++)
5095                         FS_Print(file, glslshadermodeinfo[i].pretext);
5096                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5097                         FS_Print(file, shaderpermutationinfo[i].pretext);
5098                 FS_Print(file, "*/\n");
5099                 FS_Print(file, builtinshaderstring);
5100                 FS_Close(file);
5101                 Con_Printf("glsl/default.glsl written\n");
5102         }
5103         else
5104                 Con_Printf("failed to write to glsl/default.glsl\n");
5105
5106 #ifdef SUPPORTCG
5107         file = FS_OpenRealFile("cg/default.cg", "w", false);
5108         if (file)
5109         {
5110                 FS_Print(file, "/* The engine may define the following macros:\n");
5111                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5112                 for (i = 0;i < SHADERMODE_COUNT;i++)
5113                         FS_Print(file, cgshadermodeinfo[i].pretext);
5114                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5115                         FS_Print(file, shaderpermutationinfo[i].pretext);
5116                 FS_Print(file, "*/\n");
5117                 FS_Print(file, builtincgshaderstring);
5118                 FS_Close(file);
5119                 Con_Printf("cg/default.cg written\n");
5120         }
5121         else
5122                 Con_Printf("failed to write to cg/default.cg\n");
5123 #endif
5124
5125 #ifdef SUPPORTD3D
5126         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5127         if (file)
5128         {
5129                 FS_Print(file, "/* The engine may define the following macros:\n");
5130                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5131                 for (i = 0;i < SHADERMODE_COUNT;i++)
5132                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5133                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5134                         FS_Print(file, shaderpermutationinfo[i].pretext);
5135                 FS_Print(file, "*/\n");
5136                 FS_Print(file, builtincgshaderstring);
5137                 FS_Close(file);
5138                 Con_Printf("hlsl/default.hlsl written\n");
5139         }
5140         else
5141                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5142 #endif
5143 }
5144
5145 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5146 {
5147         if (!second)
5148                 texturemode = GL_MODULATE;
5149         switch (vid.renderpath)
5150         {
5151         case RENDERPATH_D3D9:
5152 #ifdef SUPPORTD3D
5153                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5154                 R_Mesh_TexBind(GL20TU_FIRST , first );
5155                 R_Mesh_TexBind(GL20TU_SECOND, second);
5156 #endif
5157                 break;
5158         case RENDERPATH_D3D10:
5159                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5160                 break;
5161         case RENDERPATH_D3D11:
5162                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5163                 break;
5164         case RENDERPATH_GL20:
5165                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5166                 R_Mesh_TexBind(GL20TU_FIRST , first );
5167                 R_Mesh_TexBind(GL20TU_SECOND, second);
5168                 break;
5169         case RENDERPATH_CGGL:
5170 #ifdef SUPPORTCG
5171                 CHECKCGERROR
5172                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5173                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5174                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5175 #endif
5176                 break;
5177         case RENDERPATH_GL13:
5178                 R_Mesh_TexBind(0, first );
5179                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5180                 R_Mesh_TexBind(1, second);
5181                 if (second)
5182                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5183                 break;
5184         case RENDERPATH_GL11:
5185                 R_Mesh_TexBind(0, first );
5186                 break;
5187         }
5188 }
5189
5190 void R_SetupShader_DepthOrShadow(void)
5191 {
5192         switch (vid.renderpath)
5193         {
5194         case RENDERPATH_D3D9:
5195 #ifdef SUPPORTD3D
5196                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5197 #endif
5198                 break;
5199         case RENDERPATH_D3D10:
5200                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5201                 break;
5202         case RENDERPATH_D3D11:
5203                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5204                 break;
5205         case RENDERPATH_GL20:
5206                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5207                 break;
5208         case RENDERPATH_CGGL:
5209 #ifdef SUPPORTCG
5210                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5211 #endif
5212                 break;
5213         case RENDERPATH_GL13:
5214                 R_Mesh_TexBind(0, 0);
5215                 R_Mesh_TexBind(1, 0);
5216                 break;
5217         case RENDERPATH_GL11:
5218                 R_Mesh_TexBind(0, 0);
5219                 break;
5220         }
5221 }
5222
5223 void R_SetupShader_ShowDepth(void)
5224 {
5225         switch (vid.renderpath)
5226         {
5227         case RENDERPATH_D3D9:
5228 #ifdef SUPPORTHLSL
5229                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5230 #endif
5231                 break;
5232         case RENDERPATH_D3D10:
5233                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5234                 break;
5235         case RENDERPATH_D3D11:
5236                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5237                 break;
5238         case RENDERPATH_GL20:
5239                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5240                 break;
5241         case RENDERPATH_CGGL:
5242 #ifdef SUPPORTCG
5243                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5244 #endif
5245                 break;
5246         case RENDERPATH_GL13:
5247                 break;
5248         case RENDERPATH_GL11:
5249                 break;
5250         }
5251 }
5252
5253 extern qboolean r_shadow_usingdeferredprepass;
5254 extern cvar_t r_shadow_deferred_8bitrange;
5255 extern rtexture_t *r_shadow_attenuationgradienttexture;
5256 extern rtexture_t *r_shadow_attenuation2dtexture;
5257 extern rtexture_t *r_shadow_attenuation3dtexture;
5258 extern qboolean r_shadow_usingshadowmap2d;
5259 extern qboolean r_shadow_usingshadowmaportho;
5260 extern float r_shadow_shadowmap_texturescale[2];
5261 extern float r_shadow_shadowmap_parameters[4];
5262 extern qboolean r_shadow_shadowmapvsdct;
5263 extern qboolean r_shadow_shadowmapsampler;
5264 extern int r_shadow_shadowmappcf;
5265 extern rtexture_t *r_shadow_shadowmap2dtexture;
5266 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5267 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5268 extern matrix4x4_t r_shadow_shadowmapmatrix;
5269 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5270 extern int r_shadow_prepass_width;
5271 extern int r_shadow_prepass_height;
5272 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5273 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5274 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5275 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5276 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5277 extern cvar_t gl_mesh_separatearrays;
5278 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5279 {
5280         // a blendfunc allows colormod if:
5281         // a) it can never keep the destination pixel invariant, or
5282         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5283         // this is to prevent unintended side effects from colormod
5284
5285         // in formulas:
5286         // IF there is a (s, sa) for which for all (d, da),
5287         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5288         // THEN, for this (s, sa) and all (colormod, d, da):
5289         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5290         // OBVIOUSLY, this means that
5291         //   s*colormod * src(s*colormod, d, sa, da) = 0
5292         //   dst(s*colormod, d, sa, da)              = 1
5293
5294         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5295
5296         // main condition to leave dst color invariant:
5297         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5298         //   src == GL_ZERO:
5299         //     s * 0 + d * dst(s, d, sa, da) == d
5300         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301         //       => colormod is a problem for GL_SRC_COLOR only
5302         //   src == GL_ONE:
5303         //     s + d * dst(s, d, sa, da) == d
5304         //       => s == 0
5305         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306         //       => colormod is never problematic for these
5307         //   src == GL_SRC_COLOR:
5308         //     s*s + d * dst(s, d, sa, da) == d
5309         //       => s == 0
5310         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod is never problematic for these
5312         //   src == GL_ONE_MINUS_SRC_COLOR:
5313         //     s*(1-s) + d * dst(s, d, sa, da) == d
5314         //       => s == 0 or s == 1
5315         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is a problem for GL_SRC_COLOR only
5317         //   src == GL_DST_COLOR
5318         //     s*d + d * dst(s, d, sa, da) == d
5319         //       => s == 1
5320         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5321         //       => colormod is always a problem
5322         //     or
5323         //       => s == 0
5324         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5325         //       => colormod is never problematic for these
5326         //       => BUT, we do not know s! We must assume it is problematic
5327         //       then... except in GL_ONE case, where we know all invariant
5328         //       cases are fine
5329         //   src == GL_ONE_MINUS_DST_COLOR
5330         //     s*(1-d) + d * dst(s, d, sa, da) == d
5331         //       => s == 0 (1-d is impossible to handle for our desired result)
5332         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333         //       => colormod is never problematic for these
5334         //   src == GL_SRC_ALPHA
5335         //     s*sa + d * dst(s, d, sa, da) == d
5336         //       => s == 0, or sa == 0
5337         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338         //       => colormod breaks in the case GL_SRC_COLOR only
5339         //   src == GL_ONE_MINUS_SRC_ALPHA
5340         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5341         //       => s == 0, or sa == 1
5342         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5343         //       => colormod breaks in the case GL_SRC_COLOR only
5344         //   src == GL_DST_ALPHA
5345         //     s*da + d * dst(s, d, sa, da) == d
5346         //       => s == 0
5347         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5348         //       => colormod is never problematic for these
5349
5350         switch(src)
5351         {
5352                 case GL_ZERO:
5353                 case GL_ONE_MINUS_SRC_COLOR:
5354                 case GL_SRC_ALPHA:
5355                 case GL_ONE_MINUS_SRC_ALPHA:
5356                         if(dst == GL_SRC_COLOR)
5357                                 return false;
5358                         return true;
5359                 case GL_ONE:
5360                 case GL_SRC_COLOR:
5361                 case GL_ONE_MINUS_DST_COLOR:
5362                 case GL_DST_ALPHA:
5363                 case GL_ONE_MINUS_DST_ALPHA:
5364                         return true;
5365                 case GL_DST_COLOR:
5366                         if(dst == GL_ONE)
5367                                 return true;
5368                         return false;
5369                 default:
5370                         return false;
5371         }
5372 }
5373 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)
5374 {
5375         // select a permutation of the lighting shader appropriate to this
5376         // combination of texture, entity, light source, and fogging, only use the
5377         // minimum features necessary to avoid wasting rendering time in the
5378         // fragment shader on features that are not being used
5379         unsigned int permutation = 0;
5380         unsigned int mode = 0;
5381         qboolean allow_colormod;
5382         static float dummy_colormod[3] = {1, 1, 1};
5383         float *colormod = rsurface.colormod;
5384         float m16f[16];
5385         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5386         if (rsurfacepass == RSURFPASS_BACKGROUND)
5387         {
5388                 // distorted background
5389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5390                 {
5391                         mode = SHADERMODE_WATER;
5392                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5393                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5394                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5395                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5396                 }
5397                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5398                 {
5399                         mode = SHADERMODE_REFRACTION;
5400                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5401                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5402                 }
5403                 else
5404                 {
5405                         mode = SHADERMODE_GENERIC;
5406                         permutation |= SHADERPERMUTATION_DIFFUSE;
5407                         GL_BlendFunc(GL_ONE, GL_ZERO);
5408                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5409                 }
5410                 GL_AlphaTest(false);
5411         }
5412         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5413         {
5414                 if (r_glsl_offsetmapping.integer)
5415                 {
5416                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5417                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5418                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5419                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5420                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5421                         {
5422                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5423                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5424                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5425                         }
5426                 }
5427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5430                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5431                 // normalmap (deferred prepass), may use alpha test on diffuse
5432                 mode = SHADERMODE_DEFERREDGEOMETRY;
5433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435                 GL_AlphaTest(false);
5436                 GL_BlendFunc(GL_ONE, GL_ZERO);
5437                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5438         }
5439         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5440         {
5441                 if (r_glsl_offsetmapping.integer)
5442                 {
5443                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5444                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5445                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5446                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5447                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5448                         {
5449                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5450                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5451                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5452                         }
5453                 }
5454                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5455                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5456                 // light source
5457                 mode = SHADERMODE_LIGHTSOURCE;
5458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5459                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5460                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5461                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5462                 if (diffusescale > 0)
5463                         permutation |= SHADERPERMUTATION_DIFFUSE;
5464                 if (specularscale > 0)
5465                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5466                 if (r_refdef.fogenabled)
5467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5468                 if (rsurface.texture->colormapping)
5469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5470                 if (r_shadow_usingshadowmap2d)
5471                 {
5472                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5473                         if(r_shadow_shadowmapvsdct)
5474                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5475
5476                         if (r_shadow_shadowmapsampler)
5477                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5478                         if (r_shadow_shadowmappcf > 1)
5479                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5480                         else if (r_shadow_shadowmappcf)
5481                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5482                 }
5483                 if (rsurface.texture->reflectmasktexture)
5484                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5485                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5486                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5487                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5488         }
5489         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5490         {
5491                 if (r_glsl_offsetmapping.integer)
5492                 {
5493                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5494                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5495                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5496                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5497                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5498                         {
5499                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5500                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5501                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5502                         }
5503                 }
5504                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5505                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5506                 // unshaded geometry (fullbright or ambient model lighting)
5507                 mode = SHADERMODE_FLATCOLOR;
5508                 ambientscale = diffusescale = specularscale = 0;
5509                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5510                         permutation |= SHADERPERMUTATION_GLOW;
5511                 if (r_refdef.fogenabled)
5512                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5513                 if (rsurface.texture->colormapping)
5514                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5515                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5516                 {
5517                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5518                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5519
5520                         if (r_shadow_shadowmapsampler)
5521                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5522                         if (r_shadow_shadowmappcf > 1)
5523                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5524                         else if (r_shadow_shadowmappcf)
5525                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5526                 }
5527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5528                         permutation |= SHADERPERMUTATION_REFLECTION;
5529                 if (rsurface.texture->reflectmasktexture)
5530                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5531                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5532                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5533                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5534         }
5535         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5536         {
5537                 if (r_glsl_offsetmapping.integer)
5538                 {
5539                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5540                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5541                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5542                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5543                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5544                         {
5545                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5546                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5547                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5548                         }
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5551                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5552                 // directional model lighting
5553                 mode = SHADERMODE_LIGHTDIRECTION;
5554                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5555                         permutation |= SHADERPERMUTATION_GLOW;
5556                 permutation |= SHADERPERMUTATION_DIFFUSE;
5557                 if (specularscale > 0)
5558                         permutation |= SHADERPERMUTATION_SPECULAR;
5559                 if (r_refdef.fogenabled)
5560                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5561                 if (rsurface.texture->colormapping)
5562                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5563                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5564                 {
5565                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5566                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5567
5568                         if (r_shadow_shadowmapsampler)
5569                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5570                         if (r_shadow_shadowmappcf > 1)
5571                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5572                         else if (r_shadow_shadowmappcf)
5573                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5574                 }
5575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5576                         permutation |= SHADERPERMUTATION_REFLECTION;
5577                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5578                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5579                 if (rsurface.texture->reflectmasktexture)
5580                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5581                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5582                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5583                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5584         }
5585         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5586         {
5587                 if (r_glsl_offsetmapping.integer)
5588                 {
5589                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5590                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5591                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5592                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5593                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5594                         {
5595                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5596                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5597                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5598                         }
5599                 }
5600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5601                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5602                 // ambient model lighting
5603                 mode = SHADERMODE_LIGHTDIRECTION;
5604                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5605                         permutation |= SHADERPERMUTATION_GLOW;
5606                 if (r_refdef.fogenabled)
5607                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5608                 if (rsurface.texture->colormapping)
5609                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5610                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5611                 {
5612                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5613                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5614
5615                         if (r_shadow_shadowmapsampler)
5616                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5617                         if (r_shadow_shadowmappcf > 1)
5618                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5619                         else if (r_shadow_shadowmappcf)
5620                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5621                 }
5622                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5623                         permutation |= SHADERPERMUTATION_REFLECTION;
5624                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5625                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5626                 if (rsurface.texture->reflectmasktexture)
5627                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5628                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5629                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5630                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5631         }
5632         else
5633         {
5634                 if (r_glsl_offsetmapping.integer)
5635                 {
5636                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5638                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5639                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5640                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5641                         {
5642                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5643                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5644                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5645                         }
5646                 }
5647                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5648                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5649                 // lightmapped wall
5650                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5651                         permutation |= SHADERPERMUTATION_GLOW;
5652                 if (r_refdef.fogenabled)
5653                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5654                 if (rsurface.texture->colormapping)
5655                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5656                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5657                 {
5658                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5659                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5660
5661                         if (r_shadow_shadowmapsampler)
5662                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5663                         if (r_shadow_shadowmappcf > 1)
5664                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5665                         else if (r_shadow_shadowmappcf)
5666                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5667                 }
5668                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5669                         permutation |= SHADERPERMUTATION_REFLECTION;
5670                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5671                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5672                 if (rsurface.texture->reflectmasktexture)
5673                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5674                 if (FAKELIGHT_ENABLED)
5675                 {
5676                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5677                         mode = SHADERMODE_FAKELIGHT;
5678                         permutation |= SHADERPERMUTATION_DIFFUSE;
5679                         if (specularscale > 0)
5680                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5681                 }
5682                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5683                 {
5684                         // deluxemapping (light direction texture)
5685                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5686                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5687                         else
5688                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5689                         permutation |= SHADERPERMUTATION_DIFFUSE;
5690                         if (specularscale > 0)
5691                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5692                 }
5693                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5694                 {
5695                         // fake deluxemapping (uniform light direction in tangentspace)
5696                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5697                         permutation |= SHADERPERMUTATION_DIFFUSE;
5698                         if (specularscale > 0)
5699                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5700                 }
5701                 else if (rsurface.uselightmaptexture)
5702                 {
5703                         // ordinary lightmapping (q1bsp, q3bsp)
5704                         mode = SHADERMODE_LIGHTMAP;
5705                 }
5706                 else
5707                 {
5708                         // ordinary vertex coloring (q3bsp)
5709                         mode = SHADERMODE_VERTEXCOLOR;
5710                 }
5711                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5712                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5713                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5714         }
5715         if(!allow_colormod)
5716                 colormod = dummy_colormod;
5717         switch(vid.renderpath)
5718         {
5719         case RENDERPATH_D3D9:
5720 #ifdef SUPPORTD3D
5721                 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);
5722                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5723                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5724                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5725                 if (mode == SHADERMODE_LIGHTSOURCE)
5726                 {
5727                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5728                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5729                 }
5730                 else
5731                 {
5732                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5733                         {
5734                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5735                         }
5736                 }
5737                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5738                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5739                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5740                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5741                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5742
5743                 if (mode == SHADERMODE_LIGHTSOURCE)
5744                 {
5745                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5746                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5747                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5749                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5750
5751                         // additive passes are only darkened by fog, not tinted
5752                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5753                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5754                 }
5755                 else
5756                 {
5757                         if (mode == SHADERMODE_FLATCOLOR)
5758                         {
5759                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5760                         }
5761                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5762                         {
5763                                 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]);
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5766                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5767                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5770                         }
5771                         else
5772                         {
5773                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5775                                 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);
5776                                 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);
5777                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5778                         }
5779                         // additive passes are only darkened by fog, not tinted
5780                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5781                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5782                         else
5783                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5784                         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);
5785                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5786                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5788                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5790                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5791                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5792                         if (mode == SHADERMODE_WATER)
5793                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5794                 }
5795                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5796                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5797                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5798                 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));
5799                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5800                 if (rsurface.texture->pantstexture)
5801                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5802                 else
5803                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5804                 if (rsurface.texture->shirttexture)
5805                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5806                 else
5807                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5808                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5809                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5810                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5812                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5813                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5814                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5815
5816                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5817                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5818                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5819                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5825                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5827                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5828                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5829                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5830                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5831                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5832                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5833                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5834                 {
5835                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5836                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5837                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5838                 }
5839                 else
5840                 {
5841                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5842                 }
5843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5844 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5846                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5847                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5848                 {
5849                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5850                         if (rsurface.rtlight)
5851                         {
5852                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5853                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5854                         }
5855                 }
5856 #endif
5857                 break;
5858         case RENDERPATH_D3D10:
5859                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5860                 break;
5861         case RENDERPATH_D3D11:
5862                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5863                 break;
5864         case RENDERPATH_GL20:
5865                 if (gl_mesh_separatearrays.integer)
5866                 {
5867                         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);
5868                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5869                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5870                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5871                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5872                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5874                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5875                 }
5876                 else
5877                 {
5878                         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);
5879                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5880                 }
5881                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5882                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5883                 if (mode == SHADERMODE_LIGHTSOURCE)
5884                 {
5885                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5886                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5887                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5888                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5889                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5890                         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);
5891         
5892                         // additive passes are only darkened by fog, not tinted
5893                         if (r_glsl_permutation->loc_FogColor >= 0)
5894                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5895                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5896                 }
5897                 else
5898                 {
5899                         if (mode == SHADERMODE_FLATCOLOR)
5900                         {
5901                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5902                         }
5903                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5904                         {
5905                                 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]);
5906                                 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]);
5907                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5908                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5909                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5910                                 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]);
5911                                 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]);
5912                         }
5913                         else
5914                         {
5915                                 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]);
5916                                 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]);
5917                                 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);
5918                                 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);
5919                                 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);
5920                         }
5921                         // additive passes are only darkened by fog, not tinted
5922                         if (r_glsl_permutation->loc_FogColor >= 0)
5923                         {
5924                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5925                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5926                                 else
5927                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5928                         }
5929                         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);
5930                         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]);
5931                         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]);
5932                         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]);
5933                         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]);
5934                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5935                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5936                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5937                         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]);
5938                 }
5939                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5940                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5941                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5942                 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]);
5943                 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]);
5944
5945                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5946                 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));
5947                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5948                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5949                 {
5950                         if (rsurface.texture->pantstexture)
5951                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5952                         else
5953                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5954                 }
5955                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5956                 {
5957                         if (rsurface.texture->shirttexture)
5958                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5959                         else
5960                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5961                 }
5962                 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]);
5963                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5964                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5965                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5966                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5967                 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]);
5968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5969
5970         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5971         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5972         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5973                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5974                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5975                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5976                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5977                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5978                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5979                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5980                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5981                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5982                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5983                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5984                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5985                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5986                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5987                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5988                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5989                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5990                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5991                 {
5992                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5993                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5994                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5995                 }
5996                 else
5997                 {
5998                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5999                 }
6000 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6001 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6002                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6003                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6004                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6005                 {
6006                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6007                         if (rsurface.rtlight)
6008                         {
6009                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6010                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6011                         }
6012                 }
6013                 CHECKGLERROR
6014                 break;
6015         case RENDERPATH_CGGL:
6016 #ifdef SUPPORTCG
6017                 if (gl_mesh_separatearrays.integer)
6018                 {
6019                         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);
6020                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6021                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6022                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6023                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6024                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6026                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6027                 }
6028                 else
6029                 {
6030                         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);
6031                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6032                 }
6033                 R_SetupShader_SetPermutationCG(mode, permutation);
6034                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6035                 if (mode == SHADERMODE_LIGHTSOURCE)
6036                 {
6037                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6038                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6039                 }
6040                 else
6041                 {
6042                         if (mode == SHADERMODE_LIGHTDIRECTION)
6043                         {
6044                                 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
6045                         }
6046                 }
6047                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6048                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6049                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6050                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6051                 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
6052                 CHECKGLERROR
6053
6054                 if (mode == SHADERMODE_LIGHTSOURCE)
6055                 {
6056                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6057                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6058                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6059                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6060                         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
6061
6062                         // additive passes are only darkened by fog, not tinted
6063                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6064                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6065                 }
6066                 else
6067                 {
6068                         if (mode == SHADERMODE_FLATCOLOR)
6069                         {
6070                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6071                         }
6072                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6073                         {
6074                                 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
6075                                 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
6076                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6077                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6078                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6079                                 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
6080                                 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
6081                         }
6082                         else
6083                         {
6084                                 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
6085                                 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
6086                                 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
6087                                 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
6088                                 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
6089                         }
6090                         // additive passes are only darkened by fog, not tinted
6091                         if (r_cg_permutation->fp_FogColor)
6092                         {
6093                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6094                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6095                                 else
6096                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6097                                 CHECKCGERROR
6098                         }
6099                         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
6100                         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
6101                         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
6102                         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
6103                         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
6104                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6105                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6106                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6107                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6108                 }
6109                 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
6110                 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
6111                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6112                 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
6113                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6114                 if (r_cg_permutation->fp_Color_Pants)
6115                 {
6116                         if (rsurface.texture->pantstexture)
6117                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6118                         else
6119                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6120                         CHECKCGERROR
6121                 }
6122                 if (r_cg_permutation->fp_Color_Shirt)
6123                 {
6124                         if (rsurface.texture->shirttexture)
6125                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6126                         else
6127                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6128                         CHECKCGERROR
6129                 }
6130                 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
6131                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6132                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6133                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6134                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6135                 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
6136                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6137
6138         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6139         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6140         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6152                 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
6153                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6158                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6159                 {
6160                         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
6161                         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
6162                         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
6163                 }
6164                 else
6165                 {
6166                         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
6167                 }
6168                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6169                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6170                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6171                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6172                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6173                 {
6174                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6175                         if (rsurface.rtlight)
6176                         {
6177                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6178                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6179                         }
6180                 }
6181
6182                 CHECKGLERROR
6183 #endif
6184                 break;
6185         case RENDERPATH_GL13:
6186         case RENDERPATH_GL11:
6187                 break;
6188         }
6189 }
6190
6191 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6192 {
6193         // select a permutation of the lighting shader appropriate to this
6194         // combination of texture, entity, light source, and fogging, only use the
6195         // minimum features necessary to avoid wasting rendering time in the
6196         // fragment shader on features that are not being used
6197         unsigned int permutation = 0;
6198         unsigned int mode = 0;
6199         const float *lightcolorbase = rtlight->currentcolor;
6200         float ambientscale = rtlight->ambientscale;
6201         float diffusescale = rtlight->diffusescale;
6202         float specularscale = rtlight->specularscale;
6203         // this is the location of the light in view space
6204         vec3_t viewlightorigin;
6205         // this transforms from view space (camera) to light space (cubemap)
6206         matrix4x4_t viewtolight;
6207         matrix4x4_t lighttoview;
6208         float viewtolight16f[16];
6209         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6210         // light source
6211         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6212         if (rtlight->currentcubemap != r_texture_whitecube)
6213                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6214         if (diffusescale > 0)
6215                 permutation |= SHADERPERMUTATION_DIFFUSE;
6216         if (specularscale > 0)
6217                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6218         if (r_shadow_usingshadowmap2d)
6219         {
6220                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6221                 if (r_shadow_shadowmapvsdct)
6222                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6223
6224                 if (r_shadow_shadowmapsampler)
6225                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6226                 if (r_shadow_shadowmappcf > 1)
6227                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6228                 else if (r_shadow_shadowmappcf)
6229                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6230         }
6231         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6232         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6233         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6234         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6235         switch(vid.renderpath)
6236         {
6237         case RENDERPATH_D3D9:
6238 #ifdef SUPPORTD3D
6239                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6240                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6241                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6242                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6243                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6244                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6245                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6246                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6247                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6248                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6250
6251                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6252                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6253                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6254                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6255                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6256                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6257 #endif
6258                 break;
6259         case RENDERPATH_D3D10:
6260                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6261                 break;
6262         case RENDERPATH_D3D11:
6263                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6264                 break;
6265         case RENDERPATH_GL20:
6266                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6267                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6268                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6269                 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);
6270                 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);
6271                 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);
6272                 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]);
6273                 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]);
6274                 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));
6275                 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]);
6276                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6277
6278                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6279                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6280                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6281                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6282                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6283                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6284                 break;
6285         case RENDERPATH_CGGL:
6286 #ifdef SUPPORTCG
6287                 R_SetupShader_SetPermutationCG(mode, permutation);
6288                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6289                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6290                 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
6291                 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
6292                 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
6293                 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
6294                 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
6295                 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
6296                 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
6297                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6298
6299                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6300                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6301                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6302                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6303                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6304                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6305 #endif
6306                 break;
6307         case RENDERPATH_GL13:
6308         case RENDERPATH_GL11:
6309                 break;
6310         }
6311 }
6312
6313 #define SKINFRAME_HASH 1024
6314
6315 typedef struct
6316 {
6317         int loadsequence; // incremented each level change
6318         memexpandablearray_t array;
6319         skinframe_t *hash[SKINFRAME_HASH];
6320 }
6321 r_skinframe_t;
6322 r_skinframe_t r_skinframe;
6323
6324 void R_SkinFrame_PrepareForPurge(void)
6325 {
6326         r_skinframe.loadsequence++;
6327         // wrap it without hitting zero
6328         if (r_skinframe.loadsequence >= 200)
6329                 r_skinframe.loadsequence = 1;
6330 }
6331
6332 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6333 {
6334         if (!skinframe)
6335                 return;
6336         // mark the skinframe as used for the purging code
6337         skinframe->loadsequence = r_skinframe.loadsequence;
6338 }
6339
6340 void R_SkinFrame_Purge(void)
6341 {
6342         int i;
6343         skinframe_t *s;
6344         for (i = 0;i < SKINFRAME_HASH;i++)
6345         {
6346                 for (s = r_skinframe.hash[i];s;s = s->next)
6347                 {
6348                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6349                         {
6350                                 if (s->merged == s->base)
6351                                         s->merged = NULL;
6352                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6353                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6354                                 R_PurgeTexture(s->merged);s->merged = NULL;
6355                                 R_PurgeTexture(s->base  );s->base   = NULL;
6356                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6357                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6358                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6359                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6360                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6361                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6362                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6363                                 s->loadsequence = 0;
6364                         }
6365                 }
6366         }
6367 }
6368
6369 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6370         skinframe_t *item;
6371         char basename[MAX_QPATH];
6372
6373         Image_StripImageExtension(name, basename, sizeof(basename));
6374
6375         if( last == NULL ) {
6376                 int hashindex;
6377                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6378                 item = r_skinframe.hash[hashindex];
6379         } else {
6380                 item = last->next;
6381         }
6382
6383         // linearly search through the hash bucket
6384         for( ; item ; item = item->next ) {
6385                 if( !strcmp( item->basename, basename ) ) {
6386                         return item;
6387                 }
6388         }
6389         return NULL;
6390 }
6391
6392 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6393 {
6394         skinframe_t *item;
6395         int hashindex;
6396         char basename[MAX_QPATH];
6397
6398         Image_StripImageExtension(name, basename, sizeof(basename));
6399
6400         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6401         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6402                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6403                         break;
6404
6405         if (!item) {
6406                 rtexture_t *dyntexture;
6407                 // check whether its a dynamic texture
6408                 dyntexture = CL_GetDynTexture( basename );
6409                 if (!add && !dyntexture)
6410                         return NULL;
6411                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6412                 memset(item, 0, sizeof(*item));
6413                 strlcpy(item->basename, basename, sizeof(item->basename));
6414                 item->base = dyntexture; // either NULL or dyntexture handle
6415                 item->textureflags = textureflags;
6416                 item->comparewidth = comparewidth;
6417                 item->compareheight = compareheight;
6418                 item->comparecrc = comparecrc;
6419                 item->next = r_skinframe.hash[hashindex];
6420                 r_skinframe.hash[hashindex] = item;
6421         }
6422         else if( item->base == NULL )
6423         {
6424                 rtexture_t *dyntexture;
6425                 // check whether its a dynamic texture
6426                 // 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]
6427                 dyntexture = CL_GetDynTexture( basename );
6428                 item->base = dyntexture; // either NULL or dyntexture handle
6429         }
6430
6431         R_SkinFrame_MarkUsed(item);
6432         return item;
6433 }
6434
6435 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6436         { \
6437                 unsigned long long avgcolor[5], wsum; \
6438                 int pix, comp, w; \
6439                 avgcolor[0] = 0; \
6440                 avgcolor[1] = 0; \
6441                 avgcolor[2] = 0; \
6442                 avgcolor[3] = 0; \
6443                 avgcolor[4] = 0; \
6444                 wsum = 0; \
6445                 for(pix = 0; pix < cnt; ++pix) \
6446                 { \
6447                         w = 0; \
6448                         for(comp = 0; comp < 3; ++comp) \
6449                                 w += getpixel; \
6450                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6451                         { \
6452                                 ++wsum; \
6453                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6454                                 w = getpixel; \
6455                                 for(comp = 0; comp < 3; ++comp) \
6456                                         avgcolor[comp] += getpixel * w; \
6457                                 avgcolor[3] += w; \
6458                         } \
6459                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6460                         avgcolor[4] += getpixel; \
6461                 } \
6462                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6463                         avgcolor[3] = 1; \
6464                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6465                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6466                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6467                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6468         }
6469
6470 extern cvar_t gl_picmip;
6471 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6472 {
6473         int j;
6474         unsigned char *pixels;
6475         unsigned char *bumppixels;
6476         unsigned char *basepixels = NULL;
6477         int basepixels_width = 0;
6478         int basepixels_height = 0;
6479         skinframe_t *skinframe;
6480         rtexture_t *ddsbase = NULL;
6481         qboolean ddshasalpha = false;
6482         float ddsavgcolor[4];
6483         char basename[MAX_QPATH];
6484         int miplevel = R_PicmipForFlags(textureflags);
6485         int savemiplevel = miplevel;
6486         int mymiplevel;
6487
6488         if (cls.state == ca_dedicated)
6489                 return NULL;
6490
6491         // return an existing skinframe if already loaded
6492         // if loading of the first image fails, don't make a new skinframe as it
6493         // would cause all future lookups of this to be missing
6494         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6495         if (skinframe && skinframe->base)
6496                 return skinframe;
6497
6498         Image_StripImageExtension(name, basename, sizeof(basename));
6499
6500         // check for DDS texture file first
6501         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6502         {
6503                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6504                 if (basepixels == NULL)
6505                         return NULL;
6506         }
6507
6508         // FIXME handle miplevel
6509
6510         if (developer_loading.integer)
6511                 Con_Printf("loading skin \"%s\"\n", name);
6512
6513         // we've got some pixels to store, so really allocate this new texture now
6514         if (!skinframe)
6515                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6516         skinframe->stain = NULL;
6517         skinframe->merged = NULL;
6518         skinframe->base = NULL;
6519         skinframe->pants = NULL;
6520         skinframe->shirt = NULL;
6521         skinframe->nmap = NULL;
6522         skinframe->gloss = NULL;
6523         skinframe->glow = NULL;
6524         skinframe->fog = NULL;
6525         skinframe->reflect = NULL;
6526         skinframe->hasalpha = false;
6527
6528         if (ddsbase)
6529         {
6530                 skinframe->base = ddsbase;
6531                 skinframe->hasalpha = ddshasalpha;
6532                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6533                 if (r_loadfog && skinframe->hasalpha)
6534                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6535                 //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]);
6536         }
6537         else
6538         {
6539                 basepixels_width = image_width;
6540                 basepixels_height = image_height;
6541                 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);
6542                 if (textureflags & TEXF_ALPHA)
6543                 {
6544                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6545                         {
6546                                 if (basepixels[j] < 255)
6547                                 {
6548                                         skinframe->hasalpha = true;
6549                                         break;
6550                                 }
6551                         }
6552                         if (r_loadfog && skinframe->hasalpha)
6553                         {
6554                                 // has transparent pixels
6555                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6556                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6557                                 {
6558                                         pixels[j+0] = 255;
6559                                         pixels[j+1] = 255;
6560                                         pixels[j+2] = 255;
6561                                         pixels[j+3] = basepixels[j+3];
6562                                 }
6563                                 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);
6564                                 Mem_Free(pixels);
6565                         }
6566                 }
6567                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6568                 //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]);
6569                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6570                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6572                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6573         }
6574
6575         if (r_loaddds)
6576         {
6577                 mymiplevel = savemiplevel;
6578                 if (r_loadnormalmap)
6579                         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);
6580                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6581                 if (r_loadgloss)
6582                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6583                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6584                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6585                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6586         }
6587
6588         // _norm is the name used by tenebrae and has been adopted as standard
6589         if (r_loadnormalmap && skinframe->nmap == NULL)
6590         {
6591                 mymiplevel = savemiplevel;
6592                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6593                 {
6594                         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);
6595                         Mem_Free(pixels);
6596                         pixels = NULL;
6597                 }
6598                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6599                 {
6600                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6601                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6602                         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);
6603                         Mem_Free(pixels);
6604                         Mem_Free(bumppixels);
6605                 }
6606                 else if (r_shadow_bumpscale_basetexture.value > 0)
6607                 {
6608                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6609                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6610                         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);
6611                         Mem_Free(pixels);
6612                 }
6613                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6614                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6615         }
6616
6617         // _luma is supported only for tenebrae compatibility
6618         // _glow is the preferred name
6619         mymiplevel = savemiplevel;
6620         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))))
6621         {
6622                 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);
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6624                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6625                 Mem_Free(pixels);pixels = NULL;
6626         }
6627
6628         mymiplevel = savemiplevel;
6629         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6630         {
6631                 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);
6632                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6633                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6634                 Mem_Free(pixels);
6635                 pixels = NULL;
6636         }
6637
6638         mymiplevel = savemiplevel;
6639         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6640         {
6641                 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);
6642                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6643                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6644                 Mem_Free(pixels);
6645                 pixels = NULL;
6646         }
6647
6648         mymiplevel = savemiplevel;
6649         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6650         {
6651                 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);
6652                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6653                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6654                 Mem_Free(pixels);
6655                 pixels = NULL;
6656         }
6657
6658         mymiplevel = savemiplevel;
6659         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6660         {
6661                 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);
6662                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6663                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6664                 Mem_Free(pixels);
6665                 pixels = NULL;
6666         }
6667
6668         if (basepixels)
6669                 Mem_Free(basepixels);
6670
6671         return skinframe;
6672 }
6673
6674 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6675 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6676 {
6677         int i;
6678         unsigned char *temp1, *temp2;
6679         skinframe_t *skinframe;
6680
6681         if (cls.state == ca_dedicated)
6682                 return NULL;
6683
6684         // if already loaded just return it, otherwise make a new skinframe
6685         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6686         if (skinframe && skinframe->base)
6687                 return skinframe;
6688
6689         skinframe->stain = NULL;
6690         skinframe->merged = NULL;
6691         skinframe->base = NULL;
6692         skinframe->pants = NULL;
6693         skinframe->shirt = NULL;
6694         skinframe->nmap = NULL;
6695         skinframe->gloss = NULL;
6696         skinframe->glow = NULL;
6697         skinframe->fog = NULL;
6698         skinframe->reflect = NULL;
6699         skinframe->hasalpha = false;
6700
6701         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6702         if (!skindata)
6703                 return NULL;
6704
6705         if (developer_loading.integer)
6706                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6707
6708         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6709         {
6710                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6711                 temp2 = temp1 + width * height * 4;
6712                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6713                 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);
6714                 Mem_Free(temp1);
6715         }
6716         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6717         if (textureflags & TEXF_ALPHA)
6718         {
6719                 for (i = 3;i < width * height * 4;i += 4)
6720                 {
6721                         if (skindata[i] < 255)
6722                         {
6723                                 skinframe->hasalpha = true;
6724                                 break;
6725                         }
6726                 }
6727                 if (r_loadfog && skinframe->hasalpha)
6728                 {
6729                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6730                         memcpy(fogpixels, skindata, width * height * 4);
6731                         for (i = 0;i < width * height * 4;i += 4)
6732                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6733                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6734                         Mem_Free(fogpixels);
6735                 }
6736         }
6737
6738         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6739         //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]);
6740
6741         return skinframe;
6742 }
6743
6744 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6745 {
6746         int i;
6747         int featuresmask;
6748         skinframe_t *skinframe;
6749
6750         if (cls.state == ca_dedicated)
6751                 return NULL;
6752
6753         // if already loaded just return it, otherwise make a new skinframe
6754         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6755         if (skinframe && skinframe->base)
6756                 return skinframe;
6757
6758         skinframe->stain = NULL;
6759         skinframe->merged = NULL;
6760         skinframe->base = NULL;
6761         skinframe->pants = NULL;
6762         skinframe->shirt = NULL;
6763         skinframe->nmap = NULL;
6764         skinframe->gloss = NULL;
6765         skinframe->glow = NULL;
6766         skinframe->fog = NULL;
6767         skinframe->reflect = NULL;
6768         skinframe->hasalpha = false;
6769
6770         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6771         if (!skindata)
6772                 return NULL;
6773
6774         if (developer_loading.integer)
6775                 Con_Printf("loading quake skin \"%s\"\n", name);
6776
6777         // 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)
6778         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6779         memcpy(skinframe->qpixels, skindata, width*height);
6780         skinframe->qwidth = width;
6781         skinframe->qheight = height;
6782
6783         featuresmask = 0;
6784         for (i = 0;i < width * height;i++)
6785                 featuresmask |= palette_featureflags[skindata[i]];
6786
6787         skinframe->hasalpha = false;
6788         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6789         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6790         skinframe->qgeneratemerged = true;
6791         skinframe->qgeneratebase = skinframe->qhascolormapping;
6792         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6793
6794         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6795         //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]);
6796
6797         return skinframe;
6798 }
6799
6800 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6801 {
6802         int width;
6803         int height;
6804         unsigned char *skindata;
6805
6806         if (!skinframe->qpixels)
6807                 return;
6808
6809         if (!skinframe->qhascolormapping)
6810                 colormapped = false;
6811
6812         if (colormapped)
6813         {
6814                 if (!skinframe->qgeneratebase)
6815                         return;
6816         }
6817         else
6818         {
6819                 if (!skinframe->qgeneratemerged)
6820                         return;
6821         }
6822
6823         width = skinframe->qwidth;
6824         height = skinframe->qheight;
6825         skindata = skinframe->qpixels;
6826
6827         if (skinframe->qgeneratenmap)
6828         {
6829                 unsigned char *temp1, *temp2;
6830                 skinframe->qgeneratenmap = false;
6831                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6832                 temp2 = temp1 + width * height * 4;
6833                 // use either a custom palette or the quake palette
6834                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6835                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6836                 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);
6837                 Mem_Free(temp1);
6838         }
6839
6840         if (skinframe->qgenerateglow)
6841         {
6842                 skinframe->qgenerateglow = false;
6843                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6844         }
6845
6846         if (colormapped)
6847         {
6848                 skinframe->qgeneratebase = false;
6849                 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);
6850                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6851                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6852         }
6853         else
6854         {
6855                 skinframe->qgeneratemerged = false;
6856                 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);
6857         }
6858
6859         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6860         {
6861                 Mem_Free(skinframe->qpixels);
6862                 skinframe->qpixels = NULL;
6863         }
6864 }
6865
6866 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)
6867 {
6868         int i;
6869         skinframe_t *skinframe;
6870
6871         if (cls.state == ca_dedicated)
6872                 return NULL;
6873
6874         // if already loaded just return it, otherwise make a new skinframe
6875         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6876         if (skinframe && skinframe->base)
6877                 return skinframe;
6878
6879         skinframe->stain = NULL;
6880         skinframe->merged = NULL;
6881         skinframe->base = NULL;
6882         skinframe->pants = NULL;
6883         skinframe->shirt = NULL;
6884         skinframe->nmap = NULL;
6885         skinframe->gloss = NULL;
6886         skinframe->glow = NULL;
6887         skinframe->fog = NULL;
6888         skinframe->reflect = NULL;
6889         skinframe->hasalpha = false;
6890
6891         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6892         if (!skindata)
6893                 return NULL;
6894
6895         if (developer_loading.integer)
6896                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6897
6898         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6899         if (textureflags & TEXF_ALPHA)
6900         {
6901                 for (i = 0;i < width * height;i++)
6902                 {
6903                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6904                         {
6905                                 skinframe->hasalpha = true;
6906                                 break;
6907                         }
6908                 }
6909                 if (r_loadfog && skinframe->hasalpha)
6910                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6911         }
6912
6913         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6914         //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]);
6915
6916         return skinframe;
6917 }
6918
6919 skinframe_t *R_SkinFrame_LoadMissing(void)
6920 {
6921         skinframe_t *skinframe;
6922
6923         if (cls.state == ca_dedicated)
6924                 return NULL;
6925
6926         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6927         skinframe->stain = NULL;
6928         skinframe->merged = NULL;
6929         skinframe->base = NULL;
6930         skinframe->pants = NULL;
6931         skinframe->shirt = NULL;
6932         skinframe->nmap = NULL;
6933         skinframe->gloss = NULL;
6934         skinframe->glow = NULL;
6935         skinframe->fog = NULL;
6936         skinframe->reflect = NULL;
6937         skinframe->hasalpha = false;
6938
6939         skinframe->avgcolor[0] = rand() / RAND_MAX;
6940         skinframe->avgcolor[1] = rand() / RAND_MAX;
6941         skinframe->avgcolor[2] = rand() / RAND_MAX;
6942         skinframe->avgcolor[3] = 1;
6943
6944         return skinframe;
6945 }
6946
6947 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6948 typedef struct suffixinfo_s
6949 {
6950         const char *suffix;
6951         qboolean flipx, flipy, flipdiagonal;
6952 }
6953 suffixinfo_t;
6954 static suffixinfo_t suffix[3][6] =
6955 {
6956         {
6957                 {"px",   false, false, false},
6958                 {"nx",   false, false, false},
6959                 {"py",   false, false, false},
6960                 {"ny",   false, false, false},
6961                 {"pz",   false, false, false},
6962                 {"nz",   false, false, false}
6963         },
6964         {
6965                 {"posx", false, false, false},
6966                 {"negx", false, false, false},
6967                 {"posy", false, false, false},
6968                 {"negy", false, false, false},
6969                 {"posz", false, false, false},
6970                 {"negz", false, false, false}
6971         },
6972         {
6973                 {"rt",    true, false,  true},
6974                 {"lf",   false,  true,  true},
6975                 {"ft",    true,  true, false},
6976                 {"bk",   false, false, false},
6977                 {"up",    true, false,  true},
6978                 {"dn",    true, false,  true}
6979         }
6980 };
6981
6982 static int componentorder[4] = {0, 1, 2, 3};
6983
6984 rtexture_t *R_LoadCubemap(const char *basename)
6985 {
6986         int i, j, cubemapsize;
6987         unsigned char *cubemappixels, *image_buffer;
6988         rtexture_t *cubemaptexture;
6989         char name[256];
6990         // must start 0 so the first loadimagepixels has no requested width/height
6991         cubemapsize = 0;
6992         cubemappixels = NULL;
6993         cubemaptexture = NULL;
6994         // keep trying different suffix groups (posx, px, rt) until one loads
6995         for (j = 0;j < 3 && !cubemappixels;j++)
6996         {
6997                 // load the 6 images in the suffix group
6998                 for (i = 0;i < 6;i++)
6999                 {
7000                         // generate an image name based on the base and and suffix
7001                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7002                         // load it
7003                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7004                         {
7005                                 // an image loaded, make sure width and height are equal
7006                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7007                                 {
7008                                         // if this is the first image to load successfully, allocate the cubemap memory
7009                                         if (!cubemappixels && image_width >= 1)
7010                                         {
7011                                                 cubemapsize = image_width;
7012                                                 // note this clears to black, so unavailable sides are black
7013                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7014                                         }
7015                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7016                                         if (cubemappixels)
7017                                                 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);
7018                                 }
7019                                 else
7020                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7021                                 // free the image
7022                                 Mem_Free(image_buffer);
7023                         }
7024                 }
7025         }
7026         // if a cubemap loaded, upload it
7027         if (cubemappixels)
7028         {
7029                 if (developer_loading.integer)
7030                         Con_Printf("loading cubemap \"%s\"\n", basename);
7031
7032                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7033                 Mem_Free(cubemappixels);
7034         }
7035         else
7036         {
7037                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7038                 if (developer_loading.integer)
7039                 {
7040                         Con_Printf("(tried tried images ");
7041                         for (j = 0;j < 3;j++)
7042                                 for (i = 0;i < 6;i++)
7043                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7044                         Con_Print(" and was unable to find any of them).\n");
7045                 }
7046         }
7047         return cubemaptexture;
7048 }
7049
7050 rtexture_t *R_GetCubemap(const char *basename)
7051 {
7052         int i;
7053         for (i = 0;i < r_texture_numcubemaps;i++)
7054                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7055                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7056         if (i >= MAX_CUBEMAPS)
7057                 return r_texture_whitecube;
7058         r_texture_numcubemaps++;
7059         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7060         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7061         return r_texture_cubemaps[i].texture;
7062 }
7063
7064 void R_FreeCubemaps(void)
7065 {
7066         int i;
7067         for (i = 0;i < r_texture_numcubemaps;i++)
7068         {
7069                 if (developer_loading.integer)
7070                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7071                 if (r_texture_cubemaps[i].texture)
7072                         R_FreeTexture(r_texture_cubemaps[i].texture);
7073         }
7074         r_texture_numcubemaps = 0;
7075 }
7076
7077 void R_Main_FreeViewCache(void)
7078 {
7079         if (r_refdef.viewcache.entityvisible)
7080                 Mem_Free(r_refdef.viewcache.entityvisible);
7081         if (r_refdef.viewcache.world_pvsbits)
7082                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7083         if (r_refdef.viewcache.world_leafvisible)
7084                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7085         if (r_refdef.viewcache.world_surfacevisible)
7086                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7087         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7088 }
7089
7090 void R_Main_ResizeViewCache(void)
7091 {
7092         int numentities = r_refdef.scene.numentities;
7093         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7094         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7095         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7096         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7097         if (r_refdef.viewcache.maxentities < numentities)
7098         {
7099                 r_refdef.viewcache.maxentities = numentities;
7100                 if (r_refdef.viewcache.entityvisible)
7101                         Mem_Free(r_refdef.viewcache.entityvisible);
7102                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7103         }
7104         if (r_refdef.viewcache.world_numclusters != numclusters)
7105         {
7106                 r_refdef.viewcache.world_numclusters = numclusters;
7107                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7108                 if (r_refdef.viewcache.world_pvsbits)
7109                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7110                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7111         }
7112         if (r_refdef.viewcache.world_numleafs != numleafs)
7113         {
7114                 r_refdef.viewcache.world_numleafs = numleafs;
7115                 if (r_refdef.viewcache.world_leafvisible)
7116                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7117                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7118         }
7119         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7120         {
7121                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7122                 if (r_refdef.viewcache.world_surfacevisible)
7123                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7124                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7125         }
7126 }
7127
7128 extern rtexture_t *loadingscreentexture;
7129 void gl_main_start(void)
7130 {
7131         loadingscreentexture = NULL;
7132         r_texture_blanknormalmap = NULL;
7133         r_texture_white = NULL;
7134         r_texture_grey128 = NULL;
7135         r_texture_black = NULL;
7136         r_texture_whitecube = NULL;
7137         r_texture_normalizationcube = NULL;
7138         r_texture_fogattenuation = NULL;
7139         r_texture_fogheighttexture = NULL;
7140         r_texture_gammaramps = NULL;
7141         r_texture_numcubemaps = 0;
7142
7143         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7144         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7145
7146         switch(vid.renderpath)
7147         {
7148         case RENDERPATH_GL20:
7149         case RENDERPATH_CGGL:
7150         case RENDERPATH_D3D9:
7151         case RENDERPATH_D3D10:
7152         case RENDERPATH_D3D11:
7153                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7154                 Cvar_SetValueQuick(&gl_combine, 1);
7155                 Cvar_SetValueQuick(&r_glsl, 1);
7156                 r_loadnormalmap = true;
7157                 r_loadgloss = true;
7158                 r_loadfog = false;
7159                 break;
7160         case RENDERPATH_GL13:
7161                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7162                 Cvar_SetValueQuick(&gl_combine, 1);
7163                 Cvar_SetValueQuick(&r_glsl, 0);
7164                 r_loadnormalmap = false;
7165                 r_loadgloss = false;
7166                 r_loadfog = true;
7167                 break;
7168         case RENDERPATH_GL11:
7169                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7170                 Cvar_SetValueQuick(&gl_combine, 0);
7171                 Cvar_SetValueQuick(&r_glsl, 0);
7172                 r_loadnormalmap = false;
7173                 r_loadgloss = false;
7174                 r_loadfog = true;
7175                 break;
7176         }
7177
7178         R_AnimCache_Free();
7179         R_FrameData_Reset();
7180
7181         r_numqueries = 0;
7182         r_maxqueries = 0;
7183         memset(r_queries, 0, sizeof(r_queries));
7184
7185         r_qwskincache = NULL;
7186         r_qwskincache_size = 0;
7187
7188         // set up r_skinframe loading system for textures
7189         memset(&r_skinframe, 0, sizeof(r_skinframe));
7190         r_skinframe.loadsequence = 1;
7191         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7192
7193         r_main_texturepool = R_AllocTexturePool();
7194         R_BuildBlankTextures();
7195         R_BuildNoTexture();
7196         if (vid.support.arb_texture_cube_map)
7197         {
7198                 R_BuildWhiteCube();
7199                 R_BuildNormalizationCube();
7200         }
7201         r_texture_fogattenuation = NULL;
7202         r_texture_fogheighttexture = NULL;
7203         r_texture_gammaramps = NULL;
7204         //r_texture_fogintensity = NULL;
7205         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7206         memset(&r_waterstate, 0, sizeof(r_waterstate));
7207         r_glsl_permutation = NULL;
7208         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7209         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7210         glslshaderstring = NULL;
7211 #ifdef SUPPORTCG
7212         r_cg_permutation = NULL;
7213         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7214         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7215         cgshaderstring = NULL;
7216 #endif
7217 #ifdef SUPPORTD3D
7218         r_hlsl_permutation = NULL;
7219         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7220         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7221         hlslshaderstring = NULL;
7222 #endif
7223         memset(&r_svbsp, 0, sizeof (r_svbsp));
7224
7225         r_refdef.fogmasktable_density = 0;
7226 }
7227
7228 void gl_main_shutdown(void)
7229 {
7230         R_AnimCache_Free();
7231         R_FrameData_Reset();
7232
7233         R_Main_FreeViewCache();
7234
7235         switch(vid.renderpath)
7236         {
7237         case RENDERPATH_GL11:
7238         case RENDERPATH_GL13:
7239         case RENDERPATH_GL20:
7240         case RENDERPATH_CGGL:
7241                 if (r_maxqueries)
7242                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7243                 break;
7244         case RENDERPATH_D3D9:
7245                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7246                 break;
7247         case RENDERPATH_D3D10:
7248                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7249                 break;
7250         case RENDERPATH_D3D11:
7251                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7252                 break;
7253         }
7254
7255         r_numqueries = 0;
7256         r_maxqueries = 0;
7257         memset(r_queries, 0, sizeof(r_queries));
7258
7259         r_qwskincache = NULL;
7260         r_qwskincache_size = 0;
7261
7262         // clear out the r_skinframe state
7263         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7264         memset(&r_skinframe, 0, sizeof(r_skinframe));
7265
7266         if (r_svbsp.nodes)
7267                 Mem_Free(r_svbsp.nodes);
7268         memset(&r_svbsp, 0, sizeof (r_svbsp));
7269         R_FreeTexturePool(&r_main_texturepool);
7270         loadingscreentexture = NULL;
7271         r_texture_blanknormalmap = NULL;
7272         r_texture_white = NULL;
7273         r_texture_grey128 = NULL;
7274         r_texture_black = NULL;
7275         r_texture_whitecube = NULL;
7276         r_texture_normalizationcube = NULL;
7277         r_texture_fogattenuation = NULL;
7278         r_texture_fogheighttexture = NULL;
7279         r_texture_gammaramps = NULL;
7280         r_texture_numcubemaps = 0;
7281         //r_texture_fogintensity = NULL;
7282         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7283         memset(&r_waterstate, 0, sizeof(r_waterstate));
7284         R_GLSL_Restart_f();
7285 }
7286
7287 extern void CL_ParseEntityLump(char *entitystring);
7288 void gl_main_newmap(void)
7289 {
7290         // FIXME: move this code to client
7291         char *entities, entname[MAX_QPATH];
7292         if (r_qwskincache)
7293                 Mem_Free(r_qwskincache);
7294         r_qwskincache = NULL;
7295         r_qwskincache_size = 0;
7296         if (cl.worldmodel)
7297         {
7298                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7299                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7300                 {
7301                         CL_ParseEntityLump(entities);
7302                         Mem_Free(entities);
7303                         return;
7304                 }
7305                 if (cl.worldmodel->brush.entities)
7306                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7307         }
7308         R_Main_FreeViewCache();
7309
7310         R_FrameData_Reset();
7311 }
7312
7313 void GL_Main_Init(void)
7314 {
7315         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7316
7317         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7318         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7319         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7320         if (gamemode == GAME_NEHAHRA)
7321         {
7322                 Cvar_RegisterVariable (&gl_fogenable);
7323                 Cvar_RegisterVariable (&gl_fogdensity);
7324                 Cvar_RegisterVariable (&gl_fogred);
7325                 Cvar_RegisterVariable (&gl_foggreen);
7326                 Cvar_RegisterVariable (&gl_fogblue);
7327                 Cvar_RegisterVariable (&gl_fogstart);
7328                 Cvar_RegisterVariable (&gl_fogend);
7329                 Cvar_RegisterVariable (&gl_skyclip);
7330         }
7331         Cvar_RegisterVariable(&r_motionblur);
7332         Cvar_RegisterVariable(&r_motionblur_maxblur);
7333         Cvar_RegisterVariable(&r_motionblur_bmin);
7334         Cvar_RegisterVariable(&r_motionblur_vmin);
7335         Cvar_RegisterVariable(&r_motionblur_vmax);
7336         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7337         Cvar_RegisterVariable(&r_motionblur_randomize);
7338         Cvar_RegisterVariable(&r_damageblur);
7339         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7340         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7341         Cvar_RegisterVariable(&r_equalize_entities_by);
7342         Cvar_RegisterVariable(&r_equalize_entities_to);
7343         Cvar_RegisterVariable(&r_depthfirst);
7344         Cvar_RegisterVariable(&r_useinfinitefarclip);
7345         Cvar_RegisterVariable(&r_farclip_base);
7346         Cvar_RegisterVariable(&r_farclip_world);
7347         Cvar_RegisterVariable(&r_nearclip);
7348         Cvar_RegisterVariable(&r_showbboxes);
7349         Cvar_RegisterVariable(&r_showsurfaces);
7350         Cvar_RegisterVariable(&r_showtris);
7351         Cvar_RegisterVariable(&r_shownormals);
7352         Cvar_RegisterVariable(&r_showlighting);
7353         Cvar_RegisterVariable(&r_showshadowvolumes);
7354         Cvar_RegisterVariable(&r_showcollisionbrushes);
7355         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7356         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7357         Cvar_RegisterVariable(&r_showdisabledepthtest);
7358         Cvar_RegisterVariable(&r_drawportals);
7359         Cvar_RegisterVariable(&r_drawentities);
7360         Cvar_RegisterVariable(&r_draw2d);
7361         Cvar_RegisterVariable(&r_drawworld);
7362         Cvar_RegisterVariable(&r_cullentities_trace);
7363         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7364         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7365         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7366         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7367         Cvar_RegisterVariable(&r_drawviewmodel);
7368         Cvar_RegisterVariable(&r_drawexteriormodel);
7369         Cvar_RegisterVariable(&r_speeds);
7370         Cvar_RegisterVariable(&r_fullbrights);
7371         Cvar_RegisterVariable(&r_wateralpha);
7372         Cvar_RegisterVariable(&r_dynamic);
7373         Cvar_RegisterVariable(&r_fakelight);
7374         Cvar_RegisterVariable(&r_fakelight_intensity);
7375         Cvar_RegisterVariable(&r_fullbright);
7376         Cvar_RegisterVariable(&r_shadows);
7377         Cvar_RegisterVariable(&r_shadows_darken);
7378         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7379         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7380         Cvar_RegisterVariable(&r_shadows_throwdistance);
7381         Cvar_RegisterVariable(&r_shadows_throwdirection);
7382         Cvar_RegisterVariable(&r_shadows_focus);
7383         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7384         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7385         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7386         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7387         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7388         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7389         Cvar_RegisterVariable(&r_fog_exp2);
7390         Cvar_RegisterVariable(&r_drawfog);
7391         Cvar_RegisterVariable(&r_transparentdepthmasking);
7392         Cvar_RegisterVariable(&r_texture_dds_load);
7393         Cvar_RegisterVariable(&r_texture_dds_save);
7394         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7395         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7396         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7397         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7398         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7399         Cvar_RegisterVariable(&r_textureunits);
7400         Cvar_RegisterVariable(&gl_combine);
7401         Cvar_RegisterVariable(&r_glsl);
7402         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7403         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7404         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7405         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7406         Cvar_RegisterVariable(&r_glsl_postprocess);
7407         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7408         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7409         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7410         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7411         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7412         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7413         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7414         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7415
7416         Cvar_RegisterVariable(&r_water);
7417         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7418         Cvar_RegisterVariable(&r_water_clippingplanebias);
7419         Cvar_RegisterVariable(&r_water_refractdistort);
7420         Cvar_RegisterVariable(&r_water_reflectdistort);
7421         Cvar_RegisterVariable(&r_water_scissormode);
7422         Cvar_RegisterVariable(&r_lerpsprites);
7423         Cvar_RegisterVariable(&r_lerpmodels);
7424         Cvar_RegisterVariable(&r_lerplightstyles);
7425         Cvar_RegisterVariable(&r_waterscroll);
7426         Cvar_RegisterVariable(&r_bloom);
7427         Cvar_RegisterVariable(&r_bloom_colorscale);
7428         Cvar_RegisterVariable(&r_bloom_brighten);
7429         Cvar_RegisterVariable(&r_bloom_blur);
7430         Cvar_RegisterVariable(&r_bloom_resolution);
7431         Cvar_RegisterVariable(&r_bloom_colorexponent);
7432         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7433         Cvar_RegisterVariable(&r_hdr);
7434         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7435         Cvar_RegisterVariable(&r_hdr_glowintensity);
7436         Cvar_RegisterVariable(&r_hdr_range);
7437         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7438         Cvar_RegisterVariable(&developer_texturelogging);
7439         Cvar_RegisterVariable(&gl_lightmaps);
7440         Cvar_RegisterVariable(&r_test);
7441         Cvar_RegisterVariable(&r_glsl_saturation);
7442         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7443         Cvar_RegisterVariable(&r_framedatasize);
7444         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7445                 Cvar_SetValue("r_fullbrights", 0);
7446         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7447
7448         Cvar_RegisterVariable(&r_track_sprites);
7449         Cvar_RegisterVariable(&r_track_sprites_flags);
7450         Cvar_RegisterVariable(&r_track_sprites_scalew);
7451         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7452         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7453         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7454 }
7455
7456 extern void R_Textures_Init(void);
7457 extern void GL_Draw_Init(void);
7458 extern void GL_Main_Init(void);
7459 extern void R_Shadow_Init(void);
7460 extern void R_Sky_Init(void);
7461 extern void GL_Surf_Init(void);
7462 extern void R_Particles_Init(void);
7463 extern void R_Explosion_Init(void);
7464 extern void gl_backend_init(void);
7465 extern void Sbar_Init(void);
7466 extern void R_LightningBeams_Init(void);
7467 extern void Mod_RenderInit(void);
7468 extern void Font_Init(void);
7469
7470 void Render_Init(void)
7471 {
7472         gl_backend_init();
7473         R_Textures_Init();
7474         GL_Main_Init();
7475         Font_Init();
7476         GL_Draw_Init();
7477         R_Shadow_Init();
7478         R_Sky_Init();
7479         GL_Surf_Init();
7480         Sbar_Init();
7481         R_Particles_Init();
7482         R_Explosion_Init();
7483         R_LightningBeams_Init();
7484         Mod_RenderInit();
7485 }
7486
7487 /*
7488 ===============
7489 GL_Init
7490 ===============
7491 */
7492 extern char *ENGINE_EXTENSIONS;
7493 void GL_Init (void)
7494 {
7495         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7496         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7497         gl_version = (const char *)qglGetString(GL_VERSION);
7498         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7499
7500         if (!gl_extensions)
7501                 gl_extensions = "";
7502         if (!gl_platformextensions)
7503                 gl_platformextensions = "";
7504
7505         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7506         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7507         Con_Printf("GL_VERSION: %s\n", gl_version);
7508         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7509         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7510
7511         VID_CheckExtensions();
7512
7513         // LordHavoc: report supported extensions
7514         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7515
7516         // clear to black (loading plaque will be seen over this)
7517         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7518 }
7519
7520 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7521 {
7522         int i;
7523         mplane_t *p;
7524         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7525         {
7526                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7527                 if (i == 4)
7528                         continue;
7529                 p = r_refdef.view.frustum + i;
7530                 switch(p->signbits)
7531                 {
7532                 default:
7533                 case 0:
7534                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7535                                 return true;
7536                         break;
7537                 case 1:
7538                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7539                                 return true;
7540                         break;
7541                 case 2:
7542                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7543                                 return true;
7544                         break;
7545                 case 3:
7546                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7547                                 return true;
7548                         break;
7549                 case 4:
7550                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7551                                 return true;
7552                         break;
7553                 case 5:
7554                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7555                                 return true;
7556                         break;
7557                 case 6:
7558                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7559                                 return true;
7560                         break;
7561                 case 7:
7562                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7563                                 return true;
7564                         break;
7565                 }
7566         }
7567         return false;
7568 }
7569
7570 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7571 {
7572         int i;
7573         const mplane_t *p;
7574         for (i = 0;i < numplanes;i++)
7575         {
7576                 p = planes + i;
7577                 switch(p->signbits)
7578                 {
7579                 default:
7580                 case 0:
7581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7582                                 return true;
7583                         break;
7584                 case 1:
7585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7586                                 return true;
7587                         break;
7588                 case 2:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 3:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 4:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 5:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 6:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 7:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 }
7613         }
7614         return false;
7615 }
7616
7617 //==================================================================================
7618
7619 // LordHavoc: this stores temporary data used within the same frame
7620
7621 qboolean r_framedata_failed;
7622 static size_t r_framedata_size;
7623 static size_t r_framedata_current;
7624 static void *r_framedata_base;
7625
7626 void R_FrameData_Reset(void)
7627 {
7628         if (r_framedata_base)
7629                 Mem_Free(r_framedata_base);
7630         r_framedata_base = NULL;
7631         r_framedata_size = 0;
7632         r_framedata_current = 0;
7633         r_framedata_failed = false;
7634 }
7635
7636 void R_FrameData_NewFrame(void)
7637 {
7638         size_t wantedsize;
7639         if (r_framedata_failed)
7640                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7641         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7642         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7643         if (r_framedata_size != wantedsize)
7644         {
7645                 r_framedata_size = wantedsize;
7646                 if (r_framedata_base)
7647                         Mem_Free(r_framedata_base);
7648                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7649         }
7650         r_framedata_current = 0;
7651         r_framedata_failed = false;
7652 }
7653
7654 void *R_FrameData_Alloc(size_t size)
7655 {
7656         void *data;
7657
7658         // align to 16 byte boundary
7659         size = (size + 15) & ~15;
7660         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7661         r_framedata_current += size;
7662
7663         // check overflow
7664         if (r_framedata_current > r_framedata_size)
7665                 r_framedata_failed = true;
7666
7667         // return NULL on everything after a failure
7668         if (r_framedata_failed)
7669                 return NULL;
7670
7671         return data;
7672 }
7673
7674 void *R_FrameData_Store(size_t size, void *data)
7675 {
7676         void *d = R_FrameData_Alloc(size);
7677         if (d)
7678                 memcpy(d, data, size);
7679         return d;
7680 }
7681
7682 //==================================================================================
7683
7684 // LordHavoc: animcache originally written by Echon, rewritten since then
7685
7686 /**
7687  * Animation cache prevents re-generating mesh data for an animated model
7688  * multiple times in one frame for lighting, shadowing, reflections, etc.
7689  */
7690
7691 void R_AnimCache_Free(void)
7692 {
7693 }
7694
7695 void R_AnimCache_ClearCache(void)
7696 {
7697         int i;
7698         entity_render_t *ent;
7699
7700         for (i = 0;i < r_refdef.scene.numentities;i++)
7701         {
7702                 ent = r_refdef.scene.entities[i];
7703                 ent->animcache_vertex3f = NULL;
7704                 ent->animcache_normal3f = NULL;
7705                 ent->animcache_svector3f = NULL;
7706                 ent->animcache_tvector3f = NULL;
7707                 ent->animcache_vertexposition = NULL;
7708                 ent->animcache_vertexmesh = NULL;
7709                 ent->animcache_vertexpositionbuffer = NULL;
7710                 ent->animcache_vertexmeshbuffer = NULL;
7711         }
7712 }
7713
7714 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7715 {
7716         int i;
7717
7718         // identical memory layout, so no need to allocate...
7719         // this also provides the vertexposition structure to everything, e.g.
7720         // depth masked rendering currently uses it even if having separate
7721         // arrays
7722         // NOTE: get rid of this optimization if changing it to e.g. 4f
7723         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7724
7725         // TODO:
7726         // get rid of following uses of VERTEXPOSITION, change to the array:
7727         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7728         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7729         // R_DrawTextureSurfaceList_DepthOnly
7730         // R_Q1BSP_DrawShadowMap
7731
7732         switch(vid.renderpath)
7733         {
7734         case RENDERPATH_GL20:
7735         case RENDERPATH_CGGL:
7736                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7737                 if (gl_mesh_separatearrays.integer)
7738                         return;
7739                 break;
7740         case RENDERPATH_D3D9:
7741         case RENDERPATH_D3D10:
7742         case RENDERPATH_D3D11:
7743                 // always need the meshbuffers
7744                 break;
7745         case RENDERPATH_GL13:
7746         case RENDERPATH_GL11:
7747                 // never need the meshbuffers
7748                 return;
7749         }
7750
7751         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7752                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7753         /*
7754         if (!ent->animcache_vertexposition)
7755                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7756         */
7757         if (ent->animcache_vertexposition)
7758         {
7759                 /*
7760                 for (i = 0;i < numvertices;i++)
7761                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7762                 */
7763                 // TODO: upload vertex buffer?
7764         }
7765         if (ent->animcache_vertexmesh)
7766         {
7767                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7768                 for (i = 0;i < numvertices;i++)
7769                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7770                 if (ent->animcache_svector3f)
7771                         for (i = 0;i < numvertices;i++)
7772                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7773                 if (ent->animcache_tvector3f)
7774                         for (i = 0;i < numvertices;i++)
7775                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7776                 if (ent->animcache_normal3f)
7777                         for (i = 0;i < numvertices;i++)
7778                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7779                 // TODO: upload vertex buffer?
7780         }
7781 }
7782
7783 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7784 {
7785         dp_model_t *model = ent->model;
7786         int numvertices;
7787         // see if it's already cached this frame
7788         if (ent->animcache_vertex3f)
7789         {
7790                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7791                 if (wantnormals || wanttangents)
7792                 {
7793                         if (ent->animcache_normal3f)
7794                                 wantnormals = false;
7795                         if (ent->animcache_svector3f)
7796                                 wanttangents = false;
7797                         if (wantnormals || wanttangents)
7798                         {
7799                                 numvertices = model->surfmesh.num_vertices;
7800                                 if (wantnormals)
7801                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7802                                 if (wanttangents)
7803                                 {
7804                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7805                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7806                                 }
7807                                 if (!r_framedata_failed)
7808                                 {
7809                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7810                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7811                                 }
7812                         }
7813                 }
7814         }
7815         else
7816         {
7817                 // see if this ent is worth caching
7818                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7819                         return false;
7820                 // get some memory for this entity and generate mesh data
7821                 numvertices = model->surfmesh.num_vertices;
7822                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7823                 if (wantnormals)
7824                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7825                 if (wanttangents)
7826                 {
7827                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7828                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7829                 }
7830                 if (!r_framedata_failed)
7831                 {
7832                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7833                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7834                 }
7835         }
7836         return !r_framedata_failed;
7837 }
7838
7839 void R_AnimCache_CacheVisibleEntities(void)
7840 {
7841         int i;
7842         qboolean wantnormals = true;
7843         qboolean wanttangents = !r_showsurfaces.integer;
7844
7845         switch(vid.renderpath)
7846         {
7847         case RENDERPATH_GL20:
7848         case RENDERPATH_CGGL:
7849         case RENDERPATH_D3D9:
7850         case RENDERPATH_D3D10:
7851         case RENDERPATH_D3D11:
7852                 break;
7853         case RENDERPATH_GL13:
7854         case RENDERPATH_GL11:
7855                 wanttangents = false;
7856                 break;
7857         }
7858
7859         if (r_shownormals.integer)
7860                 wanttangents = wantnormals = true;
7861
7862         // TODO: thread this
7863         // NOTE: R_PrepareRTLights() also caches entities
7864
7865         for (i = 0;i < r_refdef.scene.numentities;i++)
7866                 if (r_refdef.viewcache.entityvisible[i])
7867                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7868 }
7869
7870 //==================================================================================
7871
7872 static void R_View_UpdateEntityLighting (void)
7873 {
7874         int i;
7875         entity_render_t *ent;
7876         vec3_t tempdiffusenormal, avg;
7877         vec_t f, fa, fd, fdd;
7878         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7879
7880         for (i = 0;i < r_refdef.scene.numentities;i++)
7881         {
7882                 ent = r_refdef.scene.entities[i];
7883
7884                 // skip unseen models
7885                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7886                         continue;
7887
7888                 // skip bsp models
7889                 if (ent->model && ent->model->brush.num_leafs)
7890                 {
7891                         // TODO: use modellight for r_ambient settings on world?
7892                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7893                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7894                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7895                         continue;
7896                 }
7897
7898                 // fetch the lighting from the worldmodel data
7899                 VectorClear(ent->modellight_ambient);
7900                 VectorClear(ent->modellight_diffuse);
7901                 VectorClear(tempdiffusenormal);
7902                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7903                 {
7904                         vec3_t org;
7905                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7906
7907                         // complete lightning for lit sprites
7908                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7909                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7910                         {
7911                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7912                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7913                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7914                         }
7915                         else
7916                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7917
7918                         if(ent->flags & RENDER_EQUALIZE)
7919                         {
7920                                 // first fix up ambient lighting...
7921                                 if(r_equalize_entities_minambient.value > 0)
7922                                 {
7923                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7924                                         if(fd > 0)
7925                                         {
7926                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7927                                                 if(fa < r_equalize_entities_minambient.value * fd)
7928                                                 {
7929                                                         // solve:
7930                                                         //   fa'/fd' = minambient
7931                                                         //   fa'+0.25*fd' = fa+0.25*fd
7932                                                         //   ...
7933                                                         //   fa' = fd' * minambient
7934                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7935                                                         //   ...
7936                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7937                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7938                                                         //   ...
7939                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7940                                                         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
7941                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7942                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7943                                                 }
7944                                         }
7945                                 }
7946
7947                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7948                                 {
7949                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7950                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7951                                         if(f > 0)
7952                                         {
7953                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7954                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7955                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7956                                         }
7957                                 }
7958                         }
7959                 }
7960                 else // highly rare
7961                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7962
7963                 // move the light direction into modelspace coordinates for lighting code
7964                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7965                 if(VectorLength2(ent->modellight_lightdir) == 0)
7966                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7967                 VectorNormalize(ent->modellight_lightdir);
7968         }
7969 }
7970
7971 #define MAX_LINEOFSIGHTTRACES 64
7972
7973 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7974 {
7975         int i;
7976         vec3_t boxmins, boxmaxs;
7977         vec3_t start;
7978         vec3_t end;
7979         dp_model_t *model = r_refdef.scene.worldmodel;
7980
7981         if (!model || !model->brush.TraceLineOfSight)
7982                 return true;
7983
7984         // expand the box a little
7985         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7986         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7987         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7988         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7989         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7990         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7991
7992         // return true if eye is inside enlarged box
7993         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7994                 return true;
7995
7996         // try center
7997         VectorCopy(eye, start);
7998         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7999         if (model->brush.TraceLineOfSight(model, start, end))
8000                 return true;
8001
8002         // try various random positions
8003         for (i = 0;i < numsamples;i++)
8004         {
8005                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8006                 if (model->brush.TraceLineOfSight(model, start, end))
8007                         return true;
8008         }
8009
8010         return false;
8011 }
8012
8013
8014 static void R_View_UpdateEntityVisible (void)
8015 {
8016         int i;
8017         int renderimask;
8018         int samples;
8019         entity_render_t *ent;
8020
8021         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8022                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8023                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8024                 :                                                          RENDER_EXTERIORMODEL;
8025         if (!r_drawviewmodel.integer)
8026                 renderimask |= RENDER_VIEWMODEL;
8027         if (!r_drawexteriormodel.integer)
8028                 renderimask |= RENDER_EXTERIORMODEL;
8029         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8030         {
8031                 // worldmodel can check visibility
8032                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8033                 for (i = 0;i < r_refdef.scene.numentities;i++)
8034                 {
8035                         ent = r_refdef.scene.entities[i];
8036                         if (!(ent->flags & renderimask))
8037                         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)))
8038                         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))
8039                                 r_refdef.viewcache.entityvisible[i] = true;
8040                 }
8041                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8042                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8043                 {
8044                         for (i = 0;i < r_refdef.scene.numentities;i++)
8045                         {
8046                                 ent = r_refdef.scene.entities[i];
8047                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8048                                 {
8049                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8050                                         if (samples < 0)
8051                                                 continue; // temp entities do pvs only
8052                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8053                                                 ent->last_trace_visibility = realtime;
8054                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8055                                                 r_refdef.viewcache.entityvisible[i] = 0;
8056                                 }
8057                         }
8058                 }
8059         }
8060         else
8061         {
8062                 // no worldmodel or it can't check visibility
8063                 for (i = 0;i < r_refdef.scene.numentities;i++)
8064                 {
8065                         ent = r_refdef.scene.entities[i];
8066                         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));
8067                 }
8068         }
8069 }
8070
8071 /// only used if skyrendermasked, and normally returns false
8072 int R_DrawBrushModelsSky (void)
8073 {
8074         int i, sky;
8075         entity_render_t *ent;
8076
8077         sky = false;
8078         for (i = 0;i < r_refdef.scene.numentities;i++)
8079         {
8080                 if (!r_refdef.viewcache.entityvisible[i])
8081                         continue;
8082                 ent = r_refdef.scene.entities[i];
8083                 if (!ent->model || !ent->model->DrawSky)
8084                         continue;
8085                 ent->model->DrawSky(ent);
8086                 sky = true;
8087         }
8088         return sky;
8089 }
8090
8091 static void R_DrawNoModel(entity_render_t *ent);
8092 static void R_DrawModels(void)
8093 {
8094         int i;
8095         entity_render_t *ent;
8096
8097         for (i = 0;i < r_refdef.scene.numentities;i++)
8098         {
8099                 if (!r_refdef.viewcache.entityvisible[i])
8100                         continue;
8101                 ent = r_refdef.scene.entities[i];
8102                 r_refdef.stats.entities++;
8103                 if (ent->model && ent->model->Draw != NULL)
8104                         ent->model->Draw(ent);
8105                 else
8106                         R_DrawNoModel(ent);
8107         }
8108 }
8109
8110 static void R_DrawModelsDepth(void)
8111 {
8112         int i;
8113         entity_render_t *ent;
8114
8115         for (i = 0;i < r_refdef.scene.numentities;i++)
8116         {
8117                 if (!r_refdef.viewcache.entityvisible[i])
8118                         continue;
8119                 ent = r_refdef.scene.entities[i];
8120                 if (ent->model && ent->model->DrawDepth != NULL)
8121                         ent->model->DrawDepth(ent);
8122         }
8123 }
8124
8125 static void R_DrawModelsDebug(void)
8126 {
8127         int i;
8128         entity_render_t *ent;
8129
8130         for (i = 0;i < r_refdef.scene.numentities;i++)
8131         {
8132                 if (!r_refdef.viewcache.entityvisible[i])
8133                         continue;
8134                 ent = r_refdef.scene.entities[i];
8135                 if (ent->model && ent->model->DrawDebug != NULL)
8136                         ent->model->DrawDebug(ent);
8137         }
8138 }
8139
8140 static void R_DrawModelsAddWaterPlanes(void)
8141 {
8142         int i;
8143         entity_render_t *ent;
8144
8145         for (i = 0;i < r_refdef.scene.numentities;i++)
8146         {
8147                 if (!r_refdef.viewcache.entityvisible[i])
8148                         continue;
8149                 ent = r_refdef.scene.entities[i];
8150                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8151                         ent->model->DrawAddWaterPlanes(ent);
8152         }
8153 }
8154
8155 static void R_View_SetFrustum(const int *scissor)
8156 {
8157         int i;
8158         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8159         vec3_t forward, left, up, origin, v;
8160
8161         if(scissor)
8162         {
8163                 // flipped x coordinates (because x points left here)
8164                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8165                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8166
8167                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8168                 switch(vid.renderpath)
8169                 {
8170                         case RENDERPATH_D3D9:
8171                         case RENDERPATH_D3D10:
8172                         case RENDERPATH_D3D11:
8173                                 // non-flipped y coordinates
8174                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8175                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8176                                 break;
8177                         case RENDERPATH_GL11:
8178                         case RENDERPATH_GL13:
8179                         case RENDERPATH_GL20:
8180                         case RENDERPATH_CGGL:
8181                                 // non-flipped y coordinates
8182                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8183                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8184                                 break;
8185                 }
8186         }
8187
8188         // we can't trust r_refdef.view.forward and friends in reflected scenes
8189         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8190
8191 #if 0
8192         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8193         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8194         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8195         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8196         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8197         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8198         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8199         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8200         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8201         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8202         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8203         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8204 #endif
8205
8206 #if 0
8207         zNear = r_refdef.nearclip;
8208         nudge = 1.0 - 1.0 / (1<<23);
8209         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8210         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8211         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8212         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8213         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8214         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8215         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8216         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8217 #endif
8218
8219
8220
8221 #if 0
8222         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8223         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8224         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8225         r_refdef.view.frustum[0].dist = m[15] - m[12];
8226
8227         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8228         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8229         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8230         r_refdef.view.frustum[1].dist = m[15] + m[12];
8231
8232         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8233         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8234         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8235         r_refdef.view.frustum[2].dist = m[15] - m[13];
8236
8237         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8238         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8239         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8240         r_refdef.view.frustum[3].dist = m[15] + m[13];
8241
8242         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8243         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8244         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8245         r_refdef.view.frustum[4].dist = m[15] - m[14];
8246
8247         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8248         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8249         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8250         r_refdef.view.frustum[5].dist = m[15] + m[14];
8251 #endif
8252
8253         if (r_refdef.view.useperspective)
8254         {
8255                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8256                 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]);
8257                 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]);
8258                 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]);
8259                 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]);
8260
8261                 // then the normals from the corners relative to origin
8262                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8263                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8264                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8265                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8266
8267                 // in a NORMAL view, forward cross left == up
8268                 // in a REFLECTED view, forward cross left == down
8269                 // so our cross products above need to be adjusted for a left handed coordinate system
8270                 CrossProduct(forward, left, v);
8271                 if(DotProduct(v, up) < 0)
8272                 {
8273                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8274                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8275                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8276                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8277                 }
8278
8279                 // Leaving those out was a mistake, those were in the old code, and they
8280                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8281                 // I couldn't reproduce it after adding those normalizations. --blub
8282                 VectorNormalize(r_refdef.view.frustum[0].normal);
8283                 VectorNormalize(r_refdef.view.frustum[1].normal);
8284                 VectorNormalize(r_refdef.view.frustum[2].normal);
8285                 VectorNormalize(r_refdef.view.frustum[3].normal);
8286
8287                 // make the corners absolute
8288                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8289                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8290                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8291                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8292
8293                 // one more normal
8294                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8295
8296                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8297                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8298                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8299                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8300                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8301         }
8302         else
8303         {
8304                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8305                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8306                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8307                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8308                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8309                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8310                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8311                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8312                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8313                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8314         }
8315         r_refdef.view.numfrustumplanes = 5;
8316
8317         if (r_refdef.view.useclipplane)
8318         {
8319                 r_refdef.view.numfrustumplanes = 6;
8320                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8321         }
8322
8323         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8324                 PlaneClassify(r_refdef.view.frustum + i);
8325
8326         // LordHavoc: note to all quake engine coders, Quake had a special case
8327         // for 90 degrees which assumed a square view (wrong), so I removed it,
8328         // Quake2 has it disabled as well.
8329
8330         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8331         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8332         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8333         //PlaneClassify(&frustum[0]);
8334
8335         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8336         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8337         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8338         //PlaneClassify(&frustum[1]);
8339
8340         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8341         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8342         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8343         //PlaneClassify(&frustum[2]);
8344
8345         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8346         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8347         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8348         //PlaneClassify(&frustum[3]);
8349
8350         // nearclip plane
8351         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8352         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8353         //PlaneClassify(&frustum[4]);
8354 }
8355
8356 void R_View_UpdateWithScissor(const int *myscissor)
8357 {
8358         R_Main_ResizeViewCache();
8359         R_View_SetFrustum(myscissor);
8360         R_View_WorldVisibility(r_refdef.view.useclipplane);
8361         R_View_UpdateEntityVisible();
8362         R_View_UpdateEntityLighting();
8363 }
8364
8365 void R_View_Update(void)
8366 {
8367         R_Main_ResizeViewCache();
8368         R_View_SetFrustum(NULL);
8369         R_View_WorldVisibility(r_refdef.view.useclipplane);
8370         R_View_UpdateEntityVisible();
8371         R_View_UpdateEntityLighting();
8372 }
8373
8374 void R_SetupView(qboolean allowwaterclippingplane)
8375 {
8376         const float *customclipplane = NULL;
8377         float plane[4];
8378         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8379         {
8380                 // LordHavoc: couldn't figure out how to make this approach the
8381                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8382                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8383                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8384                         dist = r_refdef.view.clipplane.dist;
8385                 plane[0] = r_refdef.view.clipplane.normal[0];
8386                 plane[1] = r_refdef.view.clipplane.normal[1];
8387                 plane[2] = r_refdef.view.clipplane.normal[2];
8388                 plane[3] = dist;
8389                 customclipplane = plane;
8390         }
8391
8392         if (!r_refdef.view.useperspective)
8393                 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);
8394         else if (vid.stencil && r_useinfinitefarclip.integer)
8395                 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);
8396         else
8397                 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);
8398         R_SetViewport(&r_refdef.view.viewport);
8399 }
8400
8401 void R_EntityMatrix(const matrix4x4_t *matrix)
8402 {
8403         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8404         {
8405                 gl_modelmatrixchanged = false;
8406                 gl_modelmatrix = *matrix;
8407                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8408                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8409                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8410                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8411                 CHECKGLERROR
8412                 switch(vid.renderpath)
8413                 {
8414                 case RENDERPATH_D3D9:
8415 #ifdef SUPPORTD3D
8416                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8417                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8418 #endif
8419                         break;
8420                 case RENDERPATH_D3D10:
8421                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8422                         break;
8423                 case RENDERPATH_D3D11:
8424                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8425                         break;
8426                 case RENDERPATH_GL20:
8427                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8428                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8429                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8430                         break;
8431                 case RENDERPATH_CGGL:
8432 #ifdef SUPPORTCG
8433                         CHECKCGERROR
8434                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8435                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8436                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8437 #endif
8438                         break;
8439                 case RENDERPATH_GL13:
8440                 case RENDERPATH_GL11:
8441                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8442                         break;
8443                 }
8444         }
8445 }
8446
8447 void R_ResetViewRendering2D(void)
8448 {
8449         r_viewport_t viewport;
8450         DrawQ_Finish();
8451
8452         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8453         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);
8454         R_SetViewport(&viewport);
8455         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8456         GL_Color(1, 1, 1, 1);
8457         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8458         GL_BlendFunc(GL_ONE, GL_ZERO);
8459         GL_AlphaTest(false);
8460         GL_ScissorTest(false);
8461         GL_DepthMask(false);
8462         GL_DepthRange(0, 1);
8463         GL_DepthTest(false);
8464         GL_DepthFunc(GL_LEQUAL);
8465         R_EntityMatrix(&identitymatrix);
8466         R_Mesh_ResetTextureState();
8467         GL_PolygonOffset(0, 0);
8468         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8469         switch(vid.renderpath)
8470         {
8471         case RENDERPATH_GL11:
8472         case RENDERPATH_GL13:
8473         case RENDERPATH_GL20:
8474         case RENDERPATH_CGGL:
8475                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8476                 break;
8477         case RENDERPATH_D3D9:
8478         case RENDERPATH_D3D10:
8479         case RENDERPATH_D3D11:
8480                 break;
8481         }
8482         GL_CullFace(GL_NONE);
8483 }
8484
8485 void R_ResetViewRendering3D(void)
8486 {
8487         DrawQ_Finish();
8488
8489         R_SetupView(true);
8490         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8491         GL_Color(1, 1, 1, 1);
8492         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8493         GL_BlendFunc(GL_ONE, GL_ZERO);
8494         GL_AlphaTest(false);
8495         GL_ScissorTest(true);
8496         GL_DepthMask(true);
8497         GL_DepthRange(0, 1);
8498         GL_DepthTest(true);
8499         GL_DepthFunc(GL_LEQUAL);
8500         R_EntityMatrix(&identitymatrix);
8501         R_Mesh_ResetTextureState();
8502         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8503         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8504         switch(vid.renderpath)
8505         {
8506         case RENDERPATH_GL11:
8507         case RENDERPATH_GL13:
8508         case RENDERPATH_GL20:
8509         case RENDERPATH_CGGL:
8510                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8511                 break;
8512         case RENDERPATH_D3D9:
8513         case RENDERPATH_D3D10:
8514         case RENDERPATH_D3D11:
8515                 break;
8516         }
8517         GL_CullFace(r_refdef.view.cullface_back);
8518 }
8519
8520 /*
8521 ================
8522 R_RenderView_UpdateViewVectors
8523 ================
8524 */
8525 static void R_RenderView_UpdateViewVectors(void)
8526 {
8527         // break apart the view matrix into vectors for various purposes
8528         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8529         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8530         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8531         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8532         // make an inverted copy of the view matrix for tracking sprites
8533         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8534 }
8535
8536 void R_RenderScene(void);
8537 void R_RenderWaterPlanes(void);
8538
8539 static void R_Water_StartFrame(void)
8540 {
8541         int i;
8542         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8543         r_waterstate_waterplane_t *p;
8544
8545         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8546                 return;
8547
8548         switch(vid.renderpath)
8549         {
8550         case RENDERPATH_GL20:
8551         case RENDERPATH_CGGL:
8552         case RENDERPATH_D3D9:
8553         case RENDERPATH_D3D10:
8554         case RENDERPATH_D3D11:
8555                 break;
8556         case RENDERPATH_GL13:
8557         case RENDERPATH_GL11:
8558                 return;
8559         }
8560
8561         // set waterwidth and waterheight to the water resolution that will be
8562         // used (often less than the screen resolution for faster rendering)
8563         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8564         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8565
8566         // calculate desired texture sizes
8567         // can't use water if the card does not support the texture size
8568         if (!r_water.integer || r_showsurfaces.integer)
8569                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8570         else if (vid.support.arb_texture_non_power_of_two)
8571         {
8572                 texturewidth = waterwidth;
8573                 textureheight = waterheight;
8574                 camerawidth = waterwidth;
8575                 cameraheight = waterheight;
8576         }
8577         else
8578         {
8579                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8580                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8581                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8582                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8583         }
8584
8585         // allocate textures as needed
8586         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8587         {
8588                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8589                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8590                 {
8591                         if (p->texture_refraction)
8592                                 R_FreeTexture(p->texture_refraction);
8593                         p->texture_refraction = NULL;
8594                         if (p->texture_reflection)
8595                                 R_FreeTexture(p->texture_reflection);
8596                         p->texture_reflection = NULL;
8597                         if (p->texture_camera)
8598                                 R_FreeTexture(p->texture_camera);
8599                         p->texture_camera = NULL;
8600                 }
8601                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8602                 r_waterstate.texturewidth = texturewidth;
8603                 r_waterstate.textureheight = textureheight;
8604                 r_waterstate.camerawidth = camerawidth;
8605                 r_waterstate.cameraheight = cameraheight;
8606         }
8607
8608         if (r_waterstate.texturewidth)
8609         {
8610                 r_waterstate.enabled = true;
8611
8612                 // when doing a reduced render (HDR) we want to use a smaller area
8613                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8614                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8615
8616                 // set up variables that will be used in shader setup
8617                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8618                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8619                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8620                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8621         }
8622
8623         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8624         r_waterstate.numwaterplanes = 0;
8625 }
8626
8627 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8628 {
8629         int triangleindex, planeindex;
8630         const int *e;
8631         vec3_t vert[3];
8632         vec3_t normal;
8633         vec3_t center;
8634         mplane_t plane;
8635         r_waterstate_waterplane_t *p;
8636         texture_t *t = R_GetCurrentTexture(surface->texture);
8637
8638         // just use the first triangle with a valid normal for any decisions
8639         VectorClear(normal);
8640         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8641         {
8642                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8643                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8644                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8645                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8646                 if (VectorLength2(normal) >= 0.001)
8647                         break;
8648         }
8649
8650         VectorCopy(normal, plane.normal);
8651         VectorNormalize(plane.normal);
8652         plane.dist = DotProduct(vert[0], plane.normal);
8653         PlaneClassify(&plane);
8654         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8655         {
8656                 // skip backfaces (except if nocullface is set)
8657                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8658                         return;
8659                 VectorNegate(plane.normal, plane.normal);
8660                 plane.dist *= -1;
8661                 PlaneClassify(&plane);
8662         }
8663
8664
8665         // find a matching plane if there is one
8666         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8667                 if(p->camera_entity == t->camera_entity)
8668                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8669                                 break;
8670         if (planeindex >= r_waterstate.maxwaterplanes)
8671                 return; // nothing we can do, out of planes
8672
8673         // if this triangle does not fit any known plane rendered this frame, add one
8674         if (planeindex >= r_waterstate.numwaterplanes)
8675         {
8676                 // store the new plane
8677                 r_waterstate.numwaterplanes++;
8678                 p->plane = plane;
8679                 // clear materialflags and pvs
8680                 p->materialflags = 0;
8681                 p->pvsvalid = false;
8682                 p->camera_entity = t->camera_entity;
8683                 VectorCopy(surface->mins, p->mins);
8684                 VectorCopy(surface->maxs, p->maxs);
8685         }
8686         else
8687         {
8688                 // merge mins/maxs
8689                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8690                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8691                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8692                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8693                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8694                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8695         }
8696         // merge this surface's materialflags into the waterplane
8697         p->materialflags |= t->currentmaterialflags;
8698         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8699         {
8700                 // merge this surface's PVS into the waterplane
8701                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8702                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8703                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8704                 {
8705                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8706                         p->pvsvalid = true;
8707                 }
8708         }
8709 }
8710
8711 static void R_Water_ProcessPlanes(void)
8712 {
8713         int myscissor[4];
8714         r_refdef_view_t originalview;
8715         r_refdef_view_t myview;
8716         int planeindex;
8717         r_waterstate_waterplane_t *p;
8718         vec3_t visorigin;
8719
8720         originalview = r_refdef.view;
8721
8722         // make sure enough textures are allocated
8723         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8724         {
8725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8726                 {
8727                         if (!p->texture_refraction)
8728                                 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);
8729                         if (!p->texture_refraction)
8730                                 goto error;
8731                 }
8732                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8733                 {
8734                         if (!p->texture_camera)
8735                                 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);
8736                         if (!p->texture_camera)
8737                                 goto error;
8738                 }
8739
8740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8741                 {
8742                         if (!p->texture_reflection)
8743                                 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);
8744                         if (!p->texture_reflection)
8745                                 goto error;
8746                 }
8747         }
8748
8749         // render views
8750         r_refdef.view = originalview;
8751         r_refdef.view.showdebug = false;
8752         r_refdef.view.width = r_waterstate.waterwidth;
8753         r_refdef.view.height = r_waterstate.waterheight;
8754         r_refdef.view.useclipplane = true;
8755         myview = r_refdef.view;
8756         r_waterstate.renderingscene = true;
8757         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8758         {
8759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8760                 {
8761                         r_refdef.view = myview;
8762                         if(r_water_scissormode.integer)
8763                         {
8764                                 R_SetupView(true);
8765                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8766                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8767                         }
8768
8769                         // render reflected scene and copy into texture
8770                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8771                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8772                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8773                         r_refdef.view.clipplane = p->plane;
8774
8775                         // reverse the cullface settings for this render
8776                         r_refdef.view.cullface_front = GL_FRONT;
8777                         r_refdef.view.cullface_back = GL_BACK;
8778                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8779                         {
8780                                 r_refdef.view.usecustompvs = true;
8781                                 if (p->pvsvalid)
8782                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8783                                 else
8784                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8785                         }
8786
8787                         R_ResetViewRendering3D();
8788                         R_ClearScreen(r_refdef.fogenabled);
8789                         if(r_water_scissormode.integer & 2)
8790                                 R_View_UpdateWithScissor(myscissor);
8791                         else
8792                                 R_View_Update();
8793                         if(r_water_scissormode.integer & 1)
8794                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8795                         R_RenderScene();
8796
8797                         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);
8798                 }
8799
8800                 // render the normal view scene and copy into texture
8801                 // (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)
8802                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8803                 {
8804                         r_refdef.view = myview;
8805                         if(r_water_scissormode.integer)
8806                         {
8807                                 R_SetupView(true);
8808                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8809                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8810                         }
8811
8812                         r_waterstate.renderingrefraction = true;
8813
8814                         r_refdef.view.clipplane = p->plane;
8815                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8816                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8817
8818                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8819                         {
8820                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8821                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8822                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8823                                 R_RenderView_UpdateViewVectors();
8824                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8825                                 {
8826                                         r_refdef.view.usecustompvs = true;
8827                                         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);
8828                                 }
8829                         }
8830
8831                         PlaneClassify(&r_refdef.view.clipplane);
8832
8833                         R_ResetViewRendering3D();
8834                         R_ClearScreen(r_refdef.fogenabled);
8835                         if(r_water_scissormode.integer & 2)
8836                                 R_View_UpdateWithScissor(myscissor);
8837                         else
8838                                 R_View_Update();
8839                         if(r_water_scissormode.integer & 1)
8840                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8841                         R_RenderScene();
8842
8843                         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);
8844                         r_waterstate.renderingrefraction = false;
8845                 }
8846                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8847                 {
8848                         r_refdef.view = myview;
8849
8850                         r_refdef.view.clipplane = p->plane;
8851                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8852                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8853
8854                         r_refdef.view.width = r_waterstate.camerawidth;
8855                         r_refdef.view.height = r_waterstate.cameraheight;
8856                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8857                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8858
8859                         if(p->camera_entity)
8860                         {
8861                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8862                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8863                         }
8864
8865                         // note: all of the view is used for displaying... so
8866                         // there is no use in scissoring
8867
8868                         // reverse the cullface settings for this render
8869                         r_refdef.view.cullface_front = GL_FRONT;
8870                         r_refdef.view.cullface_back = GL_BACK;
8871                         // also reverse the view matrix
8872                         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
8873                         R_RenderView_UpdateViewVectors();
8874                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8875                         {
8876                                 r_refdef.view.usecustompvs = true;
8877                                 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);
8878                         }
8879                         
8880                         // camera needs no clipplane
8881                         r_refdef.view.useclipplane = false;
8882
8883                         PlaneClassify(&r_refdef.view.clipplane);
8884
8885                         R_ResetViewRendering3D();
8886                         R_ClearScreen(r_refdef.fogenabled);
8887                         R_View_Update();
8888                         R_RenderScene();
8889
8890                         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);
8891                         r_waterstate.renderingrefraction = false;
8892                 }
8893
8894         }
8895         r_waterstate.renderingscene = false;
8896         r_refdef.view = originalview;
8897         R_ResetViewRendering3D();
8898         R_ClearScreen(r_refdef.fogenabled);
8899         R_View_Update();
8900         return;
8901 error:
8902         r_refdef.view = originalview;
8903         r_waterstate.renderingscene = false;
8904         Cvar_SetValueQuick(&r_water, 0);
8905         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8906         return;
8907 }
8908
8909 void R_Bloom_StartFrame(void)
8910 {
8911         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8912
8913         switch(vid.renderpath)
8914         {
8915         case RENDERPATH_GL20:
8916         case RENDERPATH_CGGL:
8917         case RENDERPATH_D3D9:
8918         case RENDERPATH_D3D10:
8919         case RENDERPATH_D3D11:
8920                 break;
8921         case RENDERPATH_GL13:
8922         case RENDERPATH_GL11:
8923                 return;
8924         }
8925
8926         // set bloomwidth and bloomheight to the bloom resolution that will be
8927         // used (often less than the screen resolution for faster rendering)
8928         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8929         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8930         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8931         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8932         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8933
8934         // calculate desired texture sizes
8935         if (vid.support.arb_texture_non_power_of_two)
8936         {
8937                 screentexturewidth = r_refdef.view.width;
8938                 screentextureheight = r_refdef.view.height;
8939                 bloomtexturewidth = r_bloomstate.bloomwidth;
8940                 bloomtextureheight = r_bloomstate.bloomheight;
8941         }
8942         else
8943         {
8944                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8945                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8946                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8947                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8948         }
8949
8950         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))
8951         {
8952                 Cvar_SetValueQuick(&r_hdr, 0);
8953                 Cvar_SetValueQuick(&r_bloom, 0);
8954                 Cvar_SetValueQuick(&r_motionblur, 0);
8955                 Cvar_SetValueQuick(&r_damageblur, 0);
8956         }
8957
8958         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)))
8959                 screentexturewidth = screentextureheight = 0;
8960         if (!r_hdr.integer && !r_bloom.integer)
8961                 bloomtexturewidth = bloomtextureheight = 0;
8962
8963         // allocate textures as needed
8964         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8965         {
8966                 if (r_bloomstate.texture_screen)
8967                         R_FreeTexture(r_bloomstate.texture_screen);
8968                 r_bloomstate.texture_screen = NULL;
8969                 r_bloomstate.screentexturewidth = screentexturewidth;
8970                 r_bloomstate.screentextureheight = screentextureheight;
8971                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8972                         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);
8973         }
8974         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8975         {
8976                 if (r_bloomstate.texture_bloom)
8977                         R_FreeTexture(r_bloomstate.texture_bloom);
8978                 r_bloomstate.texture_bloom = NULL;
8979                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8980                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8981                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8982                         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);
8983         }
8984
8985         // when doing a reduced render (HDR) we want to use a smaller area
8986         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8987         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8988         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8989         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8990         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8991
8992         // set up a texcoord array for the full resolution screen image
8993         // (we have to keep this around to copy back during final render)
8994         r_bloomstate.screentexcoord2f[0] = 0;
8995         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8996         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8997         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8998         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8999         r_bloomstate.screentexcoord2f[5] = 0;
9000         r_bloomstate.screentexcoord2f[6] = 0;
9001         r_bloomstate.screentexcoord2f[7] = 0;
9002
9003         // set up a texcoord array for the reduced resolution bloom image
9004         // (which will be additive blended over the screen image)
9005         r_bloomstate.bloomtexcoord2f[0] = 0;
9006         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9007         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9008         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9009         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9010         r_bloomstate.bloomtexcoord2f[5] = 0;
9011         r_bloomstate.bloomtexcoord2f[6] = 0;
9012         r_bloomstate.bloomtexcoord2f[7] = 0;
9013
9014         switch(vid.renderpath)
9015         {
9016         case RENDERPATH_GL11:
9017         case RENDERPATH_GL13:
9018         case RENDERPATH_GL20:
9019         case RENDERPATH_CGGL:
9020                 break;
9021         case RENDERPATH_D3D9:
9022         case RENDERPATH_D3D10:
9023         case RENDERPATH_D3D11:
9024                 {
9025                         int i;
9026                         for (i = 0;i < 4;i++)
9027                         {
9028                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9029                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9030                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9031                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9032                         }
9033                 }
9034                 break;
9035         }
9036
9037         if (r_hdr.integer || r_bloom.integer)
9038         {
9039                 r_bloomstate.enabled = true;
9040                 r_bloomstate.hdr = r_hdr.integer != 0;
9041         }
9042
9043         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);
9044 }
9045
9046 void R_Bloom_CopyBloomTexture(float colorscale)
9047 {
9048         r_refdef.stats.bloom++;
9049
9050         // scale down screen texture to the bloom texture size
9051         CHECKGLERROR
9052         R_SetViewport(&r_bloomstate.viewport);
9053         GL_BlendFunc(GL_ONE, GL_ZERO);
9054         GL_Color(colorscale, colorscale, colorscale, 1);
9055         // 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...
9056         switch(vid.renderpath)
9057         {
9058         case RENDERPATH_GL11:
9059         case RENDERPATH_GL13:
9060         case RENDERPATH_GL20:
9061         case RENDERPATH_CGGL:
9062                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9063                 break;
9064         case RENDERPATH_D3D9:
9065         case RENDERPATH_D3D10:
9066         case RENDERPATH_D3D11:
9067                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9068                 break;
9069         }
9070         // TODO: do boxfilter scale-down in shader?
9071         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9072         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9073         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9074
9075         // we now have a bloom image in the framebuffer
9076         // copy it into the bloom image texture for later processing
9077         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);
9078         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9079 }
9080
9081 void R_Bloom_CopyHDRTexture(void)
9082 {
9083         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);
9084         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9085 }
9086
9087 void R_Bloom_MakeTexture(void)
9088 {
9089         int x, range, dir;
9090         float xoffset, yoffset, r, brighten;
9091
9092         r_refdef.stats.bloom++;
9093
9094         R_ResetViewRendering2D();
9095
9096         // we have a bloom image in the framebuffer
9097         CHECKGLERROR
9098         R_SetViewport(&r_bloomstate.viewport);
9099
9100         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9101         {
9102                 x *= 2;
9103                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9104                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9105                 GL_Color(r,r,r,1);
9106                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9107                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9108                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9109                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9110
9111                 // copy the vertically blurred bloom view to a texture
9112                 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);
9113                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9114         }
9115
9116         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9117         brighten = r_bloom_brighten.value;
9118         if (r_hdr.integer)
9119                 brighten *= r_hdr_range.value;
9120         brighten = sqrt(brighten);
9121         if(range >= 1)
9122                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9123         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9124
9125         for (dir = 0;dir < 2;dir++)
9126         {
9127                 // blend on at multiple vertical offsets to achieve a vertical blur
9128                 // TODO: do offset blends using GLSL
9129                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9130                 GL_BlendFunc(GL_ONE, GL_ZERO);
9131                 for (x = -range;x <= range;x++)
9132                 {
9133                         if (!dir){xoffset = 0;yoffset = x;}
9134                         else {xoffset = x;yoffset = 0;}
9135                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9136                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9137                         // compute a texcoord array with the specified x and y offset
9138                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9139                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9140                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9141                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9142                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9143                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9144                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9145                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9146                         // this r value looks like a 'dot' particle, fading sharply to
9147                         // black at the edges
9148                         // (probably not realistic but looks good enough)
9149                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9150                         //r = brighten/(range*2+1);
9151                         r = brighten / (range * 2 + 1);
9152                         if(range >= 1)
9153                                 r *= (1 - x*x/(float)(range*range));
9154                         GL_Color(r, r, r, 1);
9155                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9156                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9157                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9158                         GL_BlendFunc(GL_ONE, GL_ONE);
9159                 }
9160
9161                 // copy the vertically blurred bloom view to a texture
9162                 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);
9163                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9164         }
9165 }
9166
9167 void R_HDR_RenderBloomTexture(void)
9168 {
9169         int oldwidth, oldheight;
9170         float oldcolorscale;
9171
9172         oldcolorscale = r_refdef.view.colorscale;
9173         oldwidth = r_refdef.view.width;
9174         oldheight = r_refdef.view.height;
9175         r_refdef.view.width = r_bloomstate.bloomwidth;
9176         r_refdef.view.height = r_bloomstate.bloomheight;
9177
9178         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9179         // TODO: add exposure compensation features
9180         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9181
9182         r_refdef.view.showdebug = false;
9183         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9184
9185         R_ResetViewRendering3D();
9186
9187         R_ClearScreen(r_refdef.fogenabled);
9188         if (r_timereport_active)
9189                 R_TimeReport("HDRclear");
9190
9191         R_View_Update();
9192         if (r_timereport_active)
9193                 R_TimeReport("visibility");
9194
9195         // only do secondary renders with HDR if r_hdr is 2 or higher
9196         r_waterstate.numwaterplanes = 0;
9197         if (r_waterstate.enabled && r_hdr.integer >= 2)
9198                 R_RenderWaterPlanes();
9199
9200         r_refdef.view.showdebug = true;
9201         R_RenderScene();
9202         r_waterstate.numwaterplanes = 0;
9203
9204         R_ResetViewRendering2D();
9205
9206         R_Bloom_CopyHDRTexture();
9207         R_Bloom_MakeTexture();
9208
9209         // restore the view settings
9210         r_refdef.view.width = oldwidth;
9211         r_refdef.view.height = oldheight;
9212         r_refdef.view.colorscale = oldcolorscale;
9213
9214         R_ResetViewRendering3D();
9215
9216         R_ClearScreen(r_refdef.fogenabled);
9217         if (r_timereport_active)
9218                 R_TimeReport("viewclear");
9219 }
9220
9221 static void R_BlendView(void)
9222 {
9223         unsigned int permutation;
9224         float uservecs[4][4];
9225
9226         switch (vid.renderpath)
9227         {
9228         case RENDERPATH_GL20:
9229         case RENDERPATH_CGGL:
9230         case RENDERPATH_D3D9:
9231         case RENDERPATH_D3D10:
9232         case RENDERPATH_D3D11:
9233                 permutation =
9234                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9235                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9236                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9237                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9238                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9239
9240                 if (r_bloomstate.texture_screen)
9241                 {
9242                         // make sure the buffer is available
9243                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9244
9245                         R_ResetViewRendering2D();
9246
9247                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9248                         {
9249                                 // declare variables
9250                                 float speed;
9251                                 static float avgspeed;
9252
9253                                 speed = VectorLength(cl.movement_velocity);
9254
9255                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9256                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9257
9258                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9259                                 speed = bound(0, speed, 1);
9260                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9261
9262                                 // calculate values into a standard alpha
9263                                 cl.motionbluralpha = 1 - exp(-
9264                                                 (
9265                                                  (r_motionblur.value * speed / 80)
9266                                                  +
9267                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9268                                                 )
9269                                                 /
9270                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9271                                            );
9272
9273                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9274                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9275                                 // apply the blur
9276                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9277                                 {
9278                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9279                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9280                                         switch(vid.renderpath)
9281                                         {
9282                                         case RENDERPATH_GL11:
9283                                         case RENDERPATH_GL13:
9284                                         case RENDERPATH_GL20:
9285                                         case RENDERPATH_CGGL:
9286                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9287                                                 break;
9288                                         case RENDERPATH_D3D9:
9289                                         case RENDERPATH_D3D10:
9290                                         case RENDERPATH_D3D11:
9291                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9292                                                 break;
9293                                         }
9294                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9295                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9296                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9297                                 }
9298                         }
9299
9300                         // copy view into the screen texture
9301                         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);
9302                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9303                 }
9304                 else if (!r_bloomstate.texture_bloom)
9305                 {
9306                         // we may still have to do view tint...
9307                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9308                         {
9309                                 // apply a color tint to the whole view
9310                                 R_ResetViewRendering2D();
9311                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9312                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9313                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9314                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9315                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9316                         }
9317                         break; // no screen processing, no bloom, skip it
9318                 }
9319
9320                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9321                 {
9322                         // render simple bloom effect
9323                         // copy the screen and shrink it and darken it for the bloom process
9324                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9325                         // make the bloom texture
9326                         R_Bloom_MakeTexture();
9327                 }
9328
9329 #if _MSC_VER >= 1400
9330 #define sscanf sscanf_s
9331 #endif
9332                 memset(uservecs, 0, sizeof(uservecs));
9333                 if (r_glsl_postprocess_uservec1_enable.integer)
9334                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9335                 if (r_glsl_postprocess_uservec2_enable.integer)
9336                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9337                 if (r_glsl_postprocess_uservec3_enable.integer)
9338                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9339                 if (r_glsl_postprocess_uservec4_enable.integer)
9340                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9341
9342                 R_ResetViewRendering2D();
9343                 GL_Color(1, 1, 1, 1);
9344                 GL_BlendFunc(GL_ONE, GL_ZERO);
9345
9346                 switch(vid.renderpath)
9347                 {
9348                 case RENDERPATH_GL20:
9349                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9350                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9351                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9352                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9353                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9354                         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]);
9355                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9356                         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]);
9357                         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]);
9358                         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]);
9359                         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]);
9360                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9361                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9362                         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);
9363                         break;
9364                 case RENDERPATH_CGGL:
9365 #ifdef SUPPORTCG
9366                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9367                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9368                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9369                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9370                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9371                         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
9372                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9373                         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
9374                         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
9375                         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
9376                         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
9377                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9378                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9379                         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);
9380 #endif
9381                         break;
9382                 case RENDERPATH_D3D9:
9383 #ifdef SUPPORTD3D
9384                         // 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...
9385                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9386                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9387                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9388                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9389                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9390                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9391                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9392                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9393                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9394                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9395                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9396                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9397                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9398                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9399 #endif
9400                         break;
9401                 case RENDERPATH_D3D10:
9402                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9403                         break;
9404                 case RENDERPATH_D3D11:
9405                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9406                         break;
9407                 default:
9408                         break;
9409                 }
9410                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9411                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9412                 break;
9413         case RENDERPATH_GL13:
9414         case RENDERPATH_GL11:
9415                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9416                 {
9417                         // apply a color tint to the whole view
9418                         R_ResetViewRendering2D();
9419                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9420                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9421                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9422                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9423                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9424                 }
9425                 break;
9426         }
9427 }
9428
9429 matrix4x4_t r_waterscrollmatrix;
9430
9431 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9432 {
9433         if (r_refdef.fog_density)
9434         {
9435                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9436                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9437                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9438
9439                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9440                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9441                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9442                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9443
9444                 {
9445                         vec3_t fogvec;
9446                         VectorCopy(r_refdef.fogcolor, fogvec);
9447                         //   color.rgb *= ContrastBoost * SceneBrightness;
9448                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9449                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9450                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9451                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9452                 }
9453         }
9454 }
9455
9456 void R_UpdateVariables(void)
9457 {
9458         R_Textures_Frame();
9459
9460         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9461
9462         r_refdef.farclip = r_farclip_base.value;
9463         if (r_refdef.scene.worldmodel)
9464                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9465         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9466
9467         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9468                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9469         r_refdef.polygonfactor = 0;
9470         r_refdef.polygonoffset = 0;
9471         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9472         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9473
9474         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9475         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9476         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9477         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9478         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9479         if (FAKELIGHT_ENABLED)
9480         {
9481                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9482         }
9483         if (r_showsurfaces.integer)
9484         {
9485                 r_refdef.scene.rtworld = false;
9486                 r_refdef.scene.rtworldshadows = false;
9487                 r_refdef.scene.rtdlight = false;
9488                 r_refdef.scene.rtdlightshadows = false;
9489                 r_refdef.lightmapintensity = 0;
9490         }
9491
9492         if (gamemode == GAME_NEHAHRA)
9493         {
9494                 if (gl_fogenable.integer)
9495                 {
9496                         r_refdef.oldgl_fogenable = true;
9497                         r_refdef.fog_density = gl_fogdensity.value;
9498                         r_refdef.fog_red = gl_fogred.value;
9499                         r_refdef.fog_green = gl_foggreen.value;
9500                         r_refdef.fog_blue = gl_fogblue.value;
9501                         r_refdef.fog_alpha = 1;
9502                         r_refdef.fog_start = 0;
9503                         r_refdef.fog_end = gl_skyclip.value;
9504                         r_refdef.fog_height = 1<<30;
9505                         r_refdef.fog_fadedepth = 128;
9506                 }
9507                 else if (r_refdef.oldgl_fogenable)
9508                 {
9509                         r_refdef.oldgl_fogenable = false;
9510                         r_refdef.fog_density = 0;
9511                         r_refdef.fog_red = 0;
9512                         r_refdef.fog_green = 0;
9513                         r_refdef.fog_blue = 0;
9514                         r_refdef.fog_alpha = 0;
9515                         r_refdef.fog_start = 0;
9516                         r_refdef.fog_end = 0;
9517                         r_refdef.fog_height = 1<<30;
9518                         r_refdef.fog_fadedepth = 128;
9519                 }
9520         }
9521
9522         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9523         r_refdef.fog_start = max(0, r_refdef.fog_start);
9524         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9525
9526         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9527
9528         if (r_refdef.fog_density && r_drawfog.integer)
9529         {
9530                 r_refdef.fogenabled = true;
9531                 // this is the point where the fog reaches 0.9986 alpha, which we
9532                 // consider a good enough cutoff point for the texture
9533                 // (0.9986 * 256 == 255.6)
9534                 if (r_fog_exp2.integer)
9535                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9536                 else
9537                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9538                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9539                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9540                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9541                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9542                         R_BuildFogHeightTexture();
9543                 // fog color was already set
9544                 // update the fog texture
9545                 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)
9546                         R_BuildFogTexture();
9547                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9548                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9549         }
9550         else
9551                 r_refdef.fogenabled = false;
9552
9553         switch(vid.renderpath)
9554         {
9555         case RENDERPATH_GL20:
9556         case RENDERPATH_CGGL:
9557         case RENDERPATH_D3D9:
9558         case RENDERPATH_D3D10:
9559         case RENDERPATH_D3D11:
9560                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9561                 {
9562                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9563                         {
9564                                 // build GLSL gamma texture
9565 #define RAMPWIDTH 256
9566                                 unsigned short ramp[RAMPWIDTH * 3];
9567                                 unsigned char rampbgr[RAMPWIDTH][4];
9568                                 int i;
9569
9570                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9571
9572                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9573                                 for(i = 0; i < RAMPWIDTH; ++i)
9574                                 {
9575                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9576                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9577                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9578                                         rampbgr[i][3] = 0;
9579                                 }
9580                                 if (r_texture_gammaramps)
9581                                 {
9582                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9583                                 }
9584                                 else
9585                                 {
9586                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9587                                 }
9588                         }
9589                 }
9590                 else
9591                 {
9592                         // remove GLSL gamma texture
9593                 }
9594                 break;
9595         case RENDERPATH_GL13:
9596         case RENDERPATH_GL11:
9597                 break;
9598         }
9599 }
9600
9601 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9602 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9603 /*
9604 ================
9605 R_SelectScene
9606 ================
9607 */
9608 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9609         if( scenetype != r_currentscenetype ) {
9610                 // store the old scenetype
9611                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9612                 r_currentscenetype = scenetype;
9613                 // move in the new scene
9614                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9615         }
9616 }
9617
9618 /*
9619 ================
9620 R_GetScenePointer
9621 ================
9622 */
9623 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9624 {
9625         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9626         if( scenetype == r_currentscenetype ) {
9627                 return &r_refdef.scene;
9628         } else {
9629                 return &r_scenes_store[ scenetype ];
9630         }
9631 }
9632
9633 /*
9634 ================
9635 R_RenderView
9636 ================
9637 */
9638 void R_RenderView(void)
9639 {
9640         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9641         if (r_timereport_active)
9642                 R_TimeReport("start");
9643         r_textureframe++; // used only by R_GetCurrentTexture
9644         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9645
9646         if(R_CompileShader_CheckStaticParms())
9647                 R_GLSL_Restart_f();
9648
9649         if (!r_drawentities.integer)
9650                 r_refdef.scene.numentities = 0;
9651
9652         R_AnimCache_ClearCache();
9653         R_FrameData_NewFrame();
9654
9655         /* adjust for stereo display */
9656         if(R_Stereo_Active())
9657         {
9658                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
9659                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9660         }
9661
9662         if (r_refdef.view.isoverlay)
9663         {
9664                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9665                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9666                 R_TimeReport("depthclear");
9667
9668                 r_refdef.view.showdebug = false;
9669
9670                 r_waterstate.enabled = false;
9671                 r_waterstate.numwaterplanes = 0;
9672
9673                 R_RenderScene();
9674
9675                 r_refdef.view.matrix = originalmatrix;
9676
9677                 CHECKGLERROR
9678                 return;
9679         }
9680
9681         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9682         {
9683                 r_refdef.view.matrix = originalmatrix;
9684                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9685         }
9686
9687         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9688
9689         R_RenderView_UpdateViewVectors();
9690
9691         R_Shadow_UpdateWorldLightSelection();
9692
9693         R_Bloom_StartFrame();
9694         R_Water_StartFrame();
9695
9696         CHECKGLERROR
9697         if (r_timereport_active)
9698                 R_TimeReport("viewsetup");
9699
9700         R_ResetViewRendering3D();
9701
9702         if (r_refdef.view.clear || r_refdef.fogenabled)
9703         {
9704                 R_ClearScreen(r_refdef.fogenabled);
9705                 if (r_timereport_active)
9706                         R_TimeReport("viewclear");
9707         }
9708         r_refdef.view.clear = true;
9709
9710         // this produces a bloom texture to be used in R_BlendView() later
9711         if (r_hdr.integer && r_bloomstate.bloomwidth)
9712         {
9713                 R_HDR_RenderBloomTexture();
9714                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9715                 r_textureframe++; // used only by R_GetCurrentTexture
9716         }
9717
9718         r_refdef.view.showdebug = true;
9719
9720         R_View_Update();
9721         if (r_timereport_active)
9722                 R_TimeReport("visibility");
9723
9724         r_waterstate.numwaterplanes = 0;
9725         if (r_waterstate.enabled)
9726                 R_RenderWaterPlanes();
9727
9728         R_RenderScene();
9729         r_waterstate.numwaterplanes = 0;
9730
9731         R_BlendView();
9732         if (r_timereport_active)
9733                 R_TimeReport("blendview");
9734
9735         GL_Scissor(0, 0, vid.width, vid.height);
9736         GL_ScissorTest(false);
9737
9738         r_refdef.view.matrix = originalmatrix;
9739
9740         CHECKGLERROR
9741 }
9742
9743 void R_RenderWaterPlanes(void)
9744 {
9745         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9746         {
9747                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9748                 if (r_timereport_active)
9749                         R_TimeReport("waterworld");
9750         }
9751
9752         // don't let sound skip if going slow
9753         if (r_refdef.scene.extraupdate)
9754                 S_ExtraUpdate ();
9755
9756         R_DrawModelsAddWaterPlanes();
9757         if (r_timereport_active)
9758                 R_TimeReport("watermodels");
9759
9760         if (r_waterstate.numwaterplanes)
9761         {
9762                 R_Water_ProcessPlanes();
9763                 if (r_timereport_active)
9764                         R_TimeReport("waterscenes");
9765         }
9766 }
9767
9768 extern void R_DrawLightningBeams (void);
9769 extern void VM_CL_AddPolygonsToMeshQueue (void);
9770 extern void R_DrawPortals (void);
9771 extern cvar_t cl_locs_show;
9772 static void R_DrawLocs(void);
9773 static void R_DrawEntityBBoxes(void);
9774 static void R_DrawModelDecals(void);
9775 extern void R_DrawModelShadows(void);
9776 extern void R_DrawModelShadowMaps(void);
9777 extern cvar_t cl_decals_newsystem;
9778 extern qboolean r_shadow_usingdeferredprepass;
9779 void R_RenderScene(void)
9780 {
9781         qboolean shadowmapping = false;
9782
9783         if (r_timereport_active)
9784                 R_TimeReport("beginscene");
9785
9786         r_refdef.stats.renders++;
9787
9788         R_UpdateFogColor();
9789
9790         // don't let sound skip if going slow
9791         if (r_refdef.scene.extraupdate)
9792                 S_ExtraUpdate ();
9793
9794         R_MeshQueue_BeginScene();
9795
9796         R_SkyStartFrame();
9797
9798         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);
9799
9800         if (r_timereport_active)
9801                 R_TimeReport("skystartframe");
9802
9803         if (cl.csqc_vidvars.drawworld)
9804         {
9805                 // don't let sound skip if going slow
9806                 if (r_refdef.scene.extraupdate)
9807                         S_ExtraUpdate ();
9808
9809                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9810                 {
9811                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9812                         if (r_timereport_active)
9813                                 R_TimeReport("worldsky");
9814                 }
9815
9816                 if (R_DrawBrushModelsSky() && r_timereport_active)
9817                         R_TimeReport("bmodelsky");
9818
9819                 if (skyrendermasked && skyrenderlater)
9820                 {
9821                         // we have to force off the water clipping plane while rendering sky
9822                         R_SetupView(false);
9823                         R_Sky();
9824                         R_SetupView(true);
9825                         if (r_timereport_active)
9826                                 R_TimeReport("sky");
9827                 }
9828         }
9829
9830         R_AnimCache_CacheVisibleEntities();
9831         if (r_timereport_active)
9832                 R_TimeReport("animation");
9833
9834         R_Shadow_PrepareLights();
9835         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9836                 R_Shadow_PrepareModelShadows();
9837         if (r_timereport_active)
9838                 R_TimeReport("preparelights");
9839
9840         if (R_Shadow_ShadowMappingEnabled())
9841                 shadowmapping = true;
9842
9843         if (r_shadow_usingdeferredprepass)
9844                 R_Shadow_DrawPrepass();
9845
9846         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9847         {
9848                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9849                 if (r_timereport_active)
9850                         R_TimeReport("worlddepth");
9851         }
9852         if (r_depthfirst.integer >= 2)
9853         {
9854                 R_DrawModelsDepth();
9855                 if (r_timereport_active)
9856                         R_TimeReport("modeldepth");
9857         }
9858
9859         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9860         {
9861                 R_DrawModelShadowMaps();
9862                 R_ResetViewRendering3D();
9863                 // don't let sound skip if going slow
9864                 if (r_refdef.scene.extraupdate)
9865                         S_ExtraUpdate ();
9866         }
9867
9868         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9869         {
9870                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9871                 if (r_timereport_active)
9872                         R_TimeReport("world");
9873         }
9874
9875         // don't let sound skip if going slow
9876         if (r_refdef.scene.extraupdate)
9877                 S_ExtraUpdate ();
9878
9879         R_DrawModels();
9880         if (r_timereport_active)
9881                 R_TimeReport("models");
9882
9883         // don't let sound skip if going slow
9884         if (r_refdef.scene.extraupdate)
9885                 S_ExtraUpdate ();
9886
9887         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9888         {
9889                 R_DrawModelShadows();
9890                 R_ResetViewRendering3D();
9891                 // don't let sound skip if going slow
9892                 if (r_refdef.scene.extraupdate)
9893                         S_ExtraUpdate ();
9894         }
9895
9896         if (!r_shadow_usingdeferredprepass)
9897         {
9898                 R_Shadow_DrawLights();
9899                 if (r_timereport_active)
9900                         R_TimeReport("rtlights");
9901         }
9902
9903         // don't let sound skip if going slow
9904         if (r_refdef.scene.extraupdate)
9905                 S_ExtraUpdate ();
9906
9907         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9908         {
9909                 R_DrawModelShadows();
9910                 R_ResetViewRendering3D();
9911                 // don't let sound skip if going slow
9912                 if (r_refdef.scene.extraupdate)
9913                         S_ExtraUpdate ();
9914         }
9915
9916         if (cl.csqc_vidvars.drawworld)
9917         {
9918                 if (cl_decals_newsystem.integer)
9919                 {
9920                         R_DrawModelDecals();
9921                         if (r_timereport_active)
9922                                 R_TimeReport("modeldecals");
9923                 }
9924                 else
9925                 {
9926                         R_DrawDecals();
9927                         if (r_timereport_active)
9928                                 R_TimeReport("decals");
9929                 }
9930
9931                 R_DrawParticles();
9932                 if (r_timereport_active)
9933                         R_TimeReport("particles");
9934
9935                 R_DrawExplosions();
9936                 if (r_timereport_active)
9937                         R_TimeReport("explosions");
9938
9939                 R_DrawLightningBeams();
9940                 if (r_timereport_active)
9941                         R_TimeReport("lightning");
9942         }
9943
9944         VM_CL_AddPolygonsToMeshQueue();
9945
9946         if (r_refdef.view.showdebug)
9947         {
9948                 if (cl_locs_show.integer)
9949                 {
9950                         R_DrawLocs();
9951                         if (r_timereport_active)
9952                                 R_TimeReport("showlocs");
9953                 }
9954
9955                 if (r_drawportals.integer)
9956                 {
9957                         R_DrawPortals();
9958                         if (r_timereport_active)
9959                                 R_TimeReport("portals");
9960                 }
9961
9962                 if (r_showbboxes.value > 0)
9963                 {
9964                         R_DrawEntityBBoxes();
9965                         if (r_timereport_active)
9966                                 R_TimeReport("bboxes");
9967                 }
9968         }
9969
9970         R_MeshQueue_RenderTransparent();
9971         if (r_timereport_active)
9972                 R_TimeReport("drawtrans");
9973
9974         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))
9975         {
9976                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9977                 if (r_timereport_active)
9978                         R_TimeReport("worlddebug");
9979                 R_DrawModelsDebug();
9980                 if (r_timereport_active)
9981                         R_TimeReport("modeldebug");
9982         }
9983
9984         if (cl.csqc_vidvars.drawworld)
9985         {
9986                 R_Shadow_DrawCoronas();
9987                 if (r_timereport_active)
9988                         R_TimeReport("coronas");
9989         }
9990
9991 #if 0
9992         {
9993                 GL_DepthTest(false);
9994                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9995                 GL_Color(1, 1, 1, 1);
9996                 qglBegin(GL_POLYGON);
9997                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9998                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9999                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10000                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10001                 qglEnd();
10002                 qglBegin(GL_POLYGON);
10003                 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]);
10004                 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]);
10005                 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]);
10006                 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]);
10007                 qglEnd();
10008                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10009         }
10010 #endif
10011
10012         // don't let sound skip if going slow
10013         if (r_refdef.scene.extraupdate)
10014                 S_ExtraUpdate ();
10015
10016         R_ResetViewRendering2D();
10017 }
10018
10019 static const unsigned short bboxelements[36] =
10020 {
10021         5, 1, 3, 5, 3, 7,
10022         6, 2, 0, 6, 0, 4,
10023         7, 3, 2, 7, 2, 6,
10024         4, 0, 1, 4, 1, 5,
10025         4, 5, 7, 4, 7, 6,
10026         1, 0, 2, 1, 2, 3,
10027 };
10028
10029 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10030 {
10031         int i;
10032         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10033
10034         RSurf_ActiveWorldEntity();
10035
10036         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10037         GL_DepthMask(false);
10038         GL_DepthRange(0, 1);
10039         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10040 //      R_Mesh_ResetTextureState();
10041
10042         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10043         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10044         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10045         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10046         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10047         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10048         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10049         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10050         R_FillColors(color4f, 8, cr, cg, cb, ca);
10051         if (r_refdef.fogenabled)
10052         {
10053                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10054                 {
10055                         f1 = RSurf_FogVertex(v);
10056                         f2 = 1 - f1;
10057                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10058                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10059                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10060                 }
10061         }
10062         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10063         R_Mesh_ResetTextureState();
10064         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10065         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10066 }
10067
10068 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10069 {
10070         int i;
10071         float color[4];
10072         prvm_edict_t *edict;
10073         prvm_prog_t *prog_save = prog;
10074
10075         // this function draws bounding boxes of server entities
10076         if (!sv.active)
10077                 return;
10078
10079         GL_CullFace(GL_NONE);
10080         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10081
10082         prog = 0;
10083         SV_VM_Begin();
10084         for (i = 0;i < numsurfaces;i++)
10085         {
10086                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10087                 switch ((int)edict->fields.server->solid)
10088                 {
10089                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10090                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10091                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10092                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10093                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10094                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10095                 }
10096                 color[3] *= r_showbboxes.value;
10097                 color[3] = bound(0, color[3], 1);
10098                 GL_DepthTest(!r_showdisabledepthtest.integer);
10099                 GL_CullFace(r_refdef.view.cullface_front);
10100                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10101         }
10102         SV_VM_End();
10103         prog = prog_save;
10104 }
10105
10106 static void R_DrawEntityBBoxes(void)
10107 {
10108         int i;
10109         prvm_edict_t *edict;
10110         vec3_t center;
10111         prvm_prog_t *prog_save = prog;
10112
10113         // this function draws bounding boxes of server entities
10114         if (!sv.active)
10115                 return;
10116
10117         prog = 0;
10118         SV_VM_Begin();
10119         for (i = 0;i < prog->num_edicts;i++)
10120         {
10121                 edict = PRVM_EDICT_NUM(i);
10122                 if (edict->priv.server->free)
10123                         continue;
10124                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10125                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10126                         continue;
10127                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10128                         continue;
10129                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10130                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10131         }
10132         SV_VM_End();
10133         prog = prog_save;
10134 }
10135
10136 static const int nomodelelement3i[24] =
10137 {
10138         5, 2, 0,
10139         5, 1, 2,
10140         5, 0, 3,
10141         5, 3, 1,
10142         0, 2, 4,
10143         2, 1, 4,
10144         3, 0, 4,
10145         1, 3, 4
10146 };
10147
10148 static const unsigned short nomodelelement3s[24] =
10149 {
10150         5, 2, 0,
10151         5, 1, 2,
10152         5, 0, 3,
10153         5, 3, 1,
10154         0, 2, 4,
10155         2, 1, 4,
10156         3, 0, 4,
10157         1, 3, 4
10158 };
10159
10160 static const float nomodelvertex3f[6*3] =
10161 {
10162         -16,   0,   0,
10163          16,   0,   0,
10164           0, -16,   0,
10165           0,  16,   0,
10166           0,   0, -16,
10167           0,   0,  16
10168 };
10169
10170 static const float nomodelcolor4f[6*4] =
10171 {
10172         0.0f, 0.0f, 0.5f, 1.0f,
10173         0.0f, 0.0f, 0.5f, 1.0f,
10174         0.0f, 0.5f, 0.0f, 1.0f,
10175         0.0f, 0.5f, 0.0f, 1.0f,
10176         0.5f, 0.0f, 0.0f, 1.0f,
10177         0.5f, 0.0f, 0.0f, 1.0f
10178 };
10179
10180 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10181 {
10182         int i;
10183         float f1, f2, *c;
10184         float color4f[6*4];
10185
10186         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);
10187
10188         // this is only called once per entity so numsurfaces is always 1, and
10189         // surfacelist is always {0}, so this code does not handle batches
10190
10191         if (rsurface.ent_flags & RENDER_ADDITIVE)
10192         {
10193                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10194                 GL_DepthMask(false);
10195         }
10196         else if (rsurface.colormod[3] < 1)
10197         {
10198                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10199                 GL_DepthMask(false);
10200         }
10201         else
10202         {
10203                 GL_BlendFunc(GL_ONE, GL_ZERO);
10204                 GL_DepthMask(true);
10205         }
10206         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10207         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10208         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10209         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10210         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10211         for (i = 0, c = color4f;i < 6;i++, c += 4)
10212         {
10213                 c[0] *= rsurface.colormod[0];
10214                 c[1] *= rsurface.colormod[1];
10215                 c[2] *= rsurface.colormod[2];
10216                 c[3] *= rsurface.colormod[3];
10217         }
10218         if (r_refdef.fogenabled)
10219         {
10220                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10221                 {
10222                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10223                         f2 = 1 - f1;
10224                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10225                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10226                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10227                 }
10228         }
10229 //      R_Mesh_ResetTextureState();
10230         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10231         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10232         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10233 }
10234
10235 void R_DrawNoModel(entity_render_t *ent)
10236 {
10237         vec3_t org;
10238         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10239         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10240                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10241         else
10242                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10243 }
10244
10245 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10246 {
10247         vec3_t right1, right2, diff, normal;
10248
10249         VectorSubtract (org2, org1, normal);
10250
10251         // calculate 'right' vector for start
10252         VectorSubtract (r_refdef.view.origin, org1, diff);
10253         CrossProduct (normal, diff, right1);
10254         VectorNormalize (right1);
10255
10256         // calculate 'right' vector for end
10257         VectorSubtract (r_refdef.view.origin, org2, diff);
10258         CrossProduct (normal, diff, right2);
10259         VectorNormalize (right2);
10260
10261         vert[ 0] = org1[0] + width * right1[0];
10262         vert[ 1] = org1[1] + width * right1[1];
10263         vert[ 2] = org1[2] + width * right1[2];
10264         vert[ 3] = org1[0] - width * right1[0];
10265         vert[ 4] = org1[1] - width * right1[1];
10266         vert[ 5] = org1[2] - width * right1[2];
10267         vert[ 6] = org2[0] - width * right2[0];
10268         vert[ 7] = org2[1] - width * right2[1];
10269         vert[ 8] = org2[2] - width * right2[2];
10270         vert[ 9] = org2[0] + width * right2[0];
10271         vert[10] = org2[1] + width * right2[1];
10272         vert[11] = org2[2] + width * right2[2];
10273 }
10274
10275 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)
10276 {
10277         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10278         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10279         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10280         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10281         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10282         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10283         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10284         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10285         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10286         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10287         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10288         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10289 }
10290
10291 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10292 {
10293         int i;
10294         float *vertex3f;
10295         float v[3];
10296         VectorSet(v, x, y, z);
10297         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10298                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10299                         break;
10300         if (i == mesh->numvertices)
10301         {
10302                 if (mesh->numvertices < mesh->maxvertices)
10303                 {
10304                         VectorCopy(v, vertex3f);
10305                         mesh->numvertices++;
10306                 }
10307                 return mesh->numvertices;
10308         }
10309         else
10310                 return i;
10311 }
10312
10313 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10314 {
10315         int i;
10316         int *e, element[3];
10317         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10318         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10319         e = mesh->element3i + mesh->numtriangles * 3;
10320         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10321         {
10322                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10323                 if (mesh->numtriangles < mesh->maxtriangles)
10324                 {
10325                         *e++ = element[0];
10326                         *e++ = element[1];
10327                         *e++ = element[2];
10328                         mesh->numtriangles++;
10329                 }
10330                 element[1] = element[2];
10331         }
10332 }
10333
10334 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10335 {
10336         int i;
10337         int *e, element[3];
10338         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10339         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10340         e = mesh->element3i + mesh->numtriangles * 3;
10341         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10342         {
10343                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10344                 if (mesh->numtriangles < mesh->maxtriangles)
10345                 {
10346                         *e++ = element[0];
10347                         *e++ = element[1];
10348                         *e++ = element[2];
10349                         mesh->numtriangles++;
10350                 }
10351                 element[1] = element[2];
10352         }
10353 }
10354
10355 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10356 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10357 {
10358         int planenum, planenum2;
10359         int w;
10360         int tempnumpoints;
10361         mplane_t *plane, *plane2;
10362         double maxdist;
10363         double temppoints[2][256*3];
10364         // figure out how large a bounding box we need to properly compute this brush
10365         maxdist = 0;
10366         for (w = 0;w < numplanes;w++)
10367                 maxdist = max(maxdist, fabs(planes[w].dist));
10368         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10369         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10370         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10371         {
10372                 w = 0;
10373                 tempnumpoints = 4;
10374                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10375                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10376                 {
10377                         if (planenum2 == planenum)
10378                                 continue;
10379                         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);
10380                         w = !w;
10381                 }
10382                 if (tempnumpoints < 3)
10383                         continue;
10384                 // generate elements forming a triangle fan for this polygon
10385                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10386         }
10387 }
10388
10389 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)
10390 {
10391         texturelayer_t *layer;
10392         layer = t->currentlayers + t->currentnumlayers++;
10393         layer->type = type;
10394         layer->depthmask = depthmask;
10395         layer->blendfunc1 = blendfunc1;
10396         layer->blendfunc2 = blendfunc2;
10397         layer->texture = texture;
10398         layer->texmatrix = *matrix;
10399         layer->color[0] = r;
10400         layer->color[1] = g;
10401         layer->color[2] = b;
10402         layer->color[3] = a;
10403 }
10404
10405 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10406 {
10407         if(parms[0] == 0 && parms[1] == 0)
10408                 return false;
10409         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10410                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10411                         return false;
10412         return true;
10413 }
10414
10415 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10416 {
10417         double index, f;
10418         index = parms[2] + r_refdef.scene.time * parms[3];
10419         index -= floor(index);
10420         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10421         {
10422         default:
10423         case Q3WAVEFUNC_NONE:
10424         case Q3WAVEFUNC_NOISE:
10425         case Q3WAVEFUNC_COUNT:
10426                 f = 0;
10427                 break;
10428         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10429         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10430         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10431         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10432         case Q3WAVEFUNC_TRIANGLE:
10433                 index *= 4;
10434                 f = index - floor(index);
10435                 if (index < 1)
10436                         f = f;
10437                 else if (index < 2)
10438                         f = 1 - f;
10439                 else if (index < 3)
10440                         f = -f;
10441                 else
10442                         f = -(1 - f);
10443                 break;
10444         }
10445         f = parms[0] + parms[1] * f;
10446         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10447                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10448         return (float) f;
10449 }
10450
10451 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10452 {
10453         int w, h, idx;
10454         float f;
10455         float tcmat[12];
10456         matrix4x4_t matrix, temp;
10457         switch(tcmod->tcmod)
10458         {
10459                 case Q3TCMOD_COUNT:
10460                 case Q3TCMOD_NONE:
10461                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10462                                 matrix = r_waterscrollmatrix;
10463                         else
10464                                 matrix = identitymatrix;
10465                         break;
10466                 case Q3TCMOD_ENTITYTRANSLATE:
10467                         // this is used in Q3 to allow the gamecode to control texcoord
10468                         // scrolling on the entity, which is not supported in darkplaces yet.
10469                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10470                         break;
10471                 case Q3TCMOD_ROTATE:
10472                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10473                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10474                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10475                         break;
10476                 case Q3TCMOD_SCALE:
10477                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10478                         break;
10479                 case Q3TCMOD_SCROLL:
10480                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10481                         break;
10482                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10483                         w = (int) tcmod->parms[0];
10484                         h = (int) tcmod->parms[1];
10485                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10486                         f = f - floor(f);
10487                         idx = (int) floor(f * w * h);
10488                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10489                         break;
10490                 case Q3TCMOD_STRETCH:
10491                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10492                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10493                         break;
10494                 case Q3TCMOD_TRANSFORM:
10495                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10496                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10497                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10498                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10499                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10500                         break;
10501                 case Q3TCMOD_TURBULENT:
10502                         // this is handled in the RSurf_PrepareVertices function
10503                         matrix = identitymatrix;
10504                         break;
10505         }
10506         temp = *texmatrix;
10507         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10508 }
10509
10510 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10511 {
10512         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10513         char name[MAX_QPATH];
10514         skinframe_t *skinframe;
10515         unsigned char pixels[296*194];
10516         strlcpy(cache->name, skinname, sizeof(cache->name));
10517         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10518         if (developer_loading.integer)
10519                 Con_Printf("loading %s\n", name);
10520         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10521         if (!skinframe || !skinframe->base)
10522         {
10523                 unsigned char *f;
10524                 fs_offset_t filesize;
10525                 skinframe = NULL;
10526                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10527                 if (f)
10528                 {
10529                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10530                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10531                         Mem_Free(f);
10532                 }
10533         }
10534         cache->skinframe = skinframe;
10535 }
10536
10537 texture_t *R_GetCurrentTexture(texture_t *t)
10538 {
10539         int i;
10540         const entity_render_t *ent = rsurface.entity;
10541         dp_model_t *model = ent->model;
10542         q3shaderinfo_layer_tcmod_t *tcmod;
10543
10544         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10545                 return t->currentframe;
10546         t->update_lastrenderframe = r_textureframe;
10547         t->update_lastrenderentity = (void *)ent;
10548
10549         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10550                 t->camera_entity = ent->entitynumber;
10551         else
10552                 t->camera_entity = 0;
10553
10554         // switch to an alternate material if this is a q1bsp animated material
10555         {
10556                 texture_t *texture = t;
10557                 int s = rsurface.ent_skinnum;
10558                 if ((unsigned int)s >= (unsigned int)model->numskins)
10559                         s = 0;
10560                 if (model->skinscenes)
10561                 {
10562                         if (model->skinscenes[s].framecount > 1)
10563                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10564                         else
10565                                 s = model->skinscenes[s].firstframe;
10566                 }
10567                 if (s > 0)
10568                         t = t + s * model->num_surfaces;
10569                 if (t->animated)
10570                 {
10571                         // use an alternate animation if the entity's frame is not 0,
10572                         // and only if the texture has an alternate animation
10573                         if (rsurface.ent_alttextures && t->anim_total[1])
10574                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10575                         else
10576                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10577                 }
10578                 texture->currentframe = t;
10579         }
10580
10581         // update currentskinframe to be a qw skin or animation frame
10582         if (rsurface.ent_qwskin >= 0)
10583         {
10584                 i = rsurface.ent_qwskin;
10585                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10586                 {
10587                         r_qwskincache_size = cl.maxclients;
10588                         if (r_qwskincache)
10589                                 Mem_Free(r_qwskincache);
10590                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10591                 }
10592                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10593                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10594                 t->currentskinframe = r_qwskincache[i].skinframe;
10595                 if (t->currentskinframe == NULL)
10596                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10597         }
10598         else if (t->numskinframes >= 2)
10599                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10600         if (t->backgroundnumskinframes >= 2)
10601                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10602
10603         t->currentmaterialflags = t->basematerialflags;
10604         t->currentalpha = rsurface.colormod[3];
10605         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10606                 t->currentalpha *= r_wateralpha.value;
10607         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10608                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10609         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10610                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10611         if (!(rsurface.ent_flags & RENDER_LIGHT))
10612                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10613         else if (FAKELIGHT_ENABLED)
10614         {
10615                         // no modellight if using fakelight for the map
10616         }
10617         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10618         {
10619                 // pick a model lighting mode
10620                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10621                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10622                 else
10623                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10624         }
10625         if (rsurface.ent_flags & RENDER_ADDITIVE)
10626                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10627         else if (t->currentalpha < 1)
10628                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10629         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10630                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10631         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10632                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10633         if (t->backgroundnumskinframes)
10634                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10635         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10636         {
10637                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10638                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10639         }
10640         else
10641                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10642         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10643                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10644
10645         // there is no tcmod
10646         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10647         {
10648                 t->currenttexmatrix = r_waterscrollmatrix;
10649                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10650         }
10651         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10652         {
10653                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10654                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10655         }
10656
10657         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10658                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10659         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10660                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10661
10662         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10663         if (t->currentskinframe->qpixels)
10664                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10665         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10666         if (!t->basetexture)
10667                 t->basetexture = r_texture_notexture;
10668         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10669         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10670         t->nmaptexture = t->currentskinframe->nmap;
10671         if (!t->nmaptexture)
10672                 t->nmaptexture = r_texture_blanknormalmap;
10673         t->glosstexture = r_texture_black;
10674         t->glowtexture = t->currentskinframe->glow;
10675         t->fogtexture = t->currentskinframe->fog;
10676         t->reflectmasktexture = t->currentskinframe->reflect;
10677         if (t->backgroundnumskinframes)
10678         {
10679                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10680                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10681                 t->backgroundglosstexture = r_texture_black;
10682                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10683                 if (!t->backgroundnmaptexture)
10684                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10685         }
10686         else
10687         {
10688                 t->backgroundbasetexture = r_texture_white;
10689                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10690                 t->backgroundglosstexture = r_texture_black;
10691                 t->backgroundglowtexture = NULL;
10692         }
10693         t->specularpower = r_shadow_glossexponent.value;
10694         // TODO: store reference values for these in the texture?
10695         t->specularscale = 0;
10696         if (r_shadow_gloss.integer > 0)
10697         {
10698                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10699                 {
10700                         if (r_shadow_glossintensity.value > 0)
10701                         {
10702                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10703                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10704                                 t->specularscale = r_shadow_glossintensity.value;
10705                         }
10706                 }
10707                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10708                 {
10709                         t->glosstexture = r_texture_white;
10710                         t->backgroundglosstexture = r_texture_white;
10711                         t->specularscale = r_shadow_gloss2intensity.value;
10712                         t->specularpower = r_shadow_gloss2exponent.value;
10713                 }
10714         }
10715         t->specularscale *= t->specularscalemod;
10716         t->specularpower *= t->specularpowermod;
10717
10718         // lightmaps mode looks bad with dlights using actual texturing, so turn
10719         // off the colormap and glossmap, but leave the normalmap on as it still
10720         // accurately represents the shading involved
10721         if (gl_lightmaps.integer)
10722         {
10723                 t->basetexture = r_texture_grey128;
10724                 t->pantstexture = r_texture_black;
10725                 t->shirttexture = r_texture_black;
10726                 t->nmaptexture = r_texture_blanknormalmap;
10727                 t->glosstexture = r_texture_black;
10728                 t->glowtexture = NULL;
10729                 t->fogtexture = NULL;
10730                 t->reflectmasktexture = NULL;
10731                 t->backgroundbasetexture = NULL;
10732                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10733                 t->backgroundglosstexture = r_texture_black;
10734                 t->backgroundglowtexture = NULL;
10735                 t->specularscale = 0;
10736                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10737         }
10738
10739         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10740         VectorClear(t->dlightcolor);
10741         t->currentnumlayers = 0;
10742         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10743         {
10744                 int blendfunc1, blendfunc2;
10745                 qboolean depthmask;
10746                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10747                 {
10748                         blendfunc1 = GL_SRC_ALPHA;
10749                         blendfunc2 = GL_ONE;
10750                 }
10751                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10752                 {
10753                         blendfunc1 = GL_SRC_ALPHA;
10754                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10755                 }
10756                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10757                 {
10758                         blendfunc1 = t->customblendfunc[0];
10759                         blendfunc2 = t->customblendfunc[1];
10760                 }
10761                 else
10762                 {
10763                         blendfunc1 = GL_ONE;
10764                         blendfunc2 = GL_ZERO;
10765                 }
10766                 // don't colormod evilblend textures
10767                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10768                         VectorSet(t->lightmapcolor, 1, 1, 1);
10769                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10770                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10771                 {
10772                         // fullbright is not affected by r_refdef.lightmapintensity
10773                         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]);
10774                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10775                                 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]);
10776                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10777                                 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]);
10778                 }
10779                 else
10780                 {
10781                         vec3_t ambientcolor;
10782                         float colorscale;
10783                         // set the color tint used for lights affecting this surface
10784                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10785                         colorscale = 2;
10786                         // q3bsp has no lightmap updates, so the lightstylevalue that
10787                         // would normally be baked into the lightmap must be
10788                         // applied to the color
10789                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10790                         if (model->type == mod_brushq3)
10791                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10792                         colorscale *= r_refdef.lightmapintensity;
10793                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10794                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10795                         // basic lit geometry
10796                         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]);
10797                         // add pants/shirt if needed
10798                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10799                                 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]);
10800                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10801                                 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]);
10802                         // now add ambient passes if needed
10803                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10804                         {
10805                                 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]);
10806                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10807                                         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]);
10808                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10809                                         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]);
10810                         }
10811                 }
10812                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10813                         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]);
10814                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10815                 {
10816                         // if this is opaque use alpha blend which will darken the earlier
10817                         // passes cheaply.
10818                         //
10819                         // if this is an alpha blended material, all the earlier passes
10820                         // were darkened by fog already, so we only need to add the fog
10821                         // color ontop through the fog mask texture
10822                         //
10823                         // if this is an additive blended material, all the earlier passes
10824                         // were darkened by fog already, and we should not add fog color
10825                         // (because the background was not darkened, there is no fog color
10826                         // that was lost behind it).
10827                         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]);
10828                 }
10829         }
10830
10831         return t->currentframe;
10832 }
10833
10834 rsurfacestate_t rsurface;
10835
10836 void R_Mesh_ResizeArrays(int newvertices)
10837 {
10838         unsigned char *base;
10839         size_t size;
10840         if (rsurface.array_size >= newvertices)
10841                 return;
10842         if (rsurface.array_base)
10843                 Mem_Free(rsurface.array_base);
10844         rsurface.array_size = (newvertices + 1023) & ~1023;
10845         size = 0;
10846         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10847         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10848         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10849         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10850         size += rsurface.array_size * sizeof(float[3]);
10851         size += rsurface.array_size * sizeof(float[3]);
10852         size += rsurface.array_size * sizeof(float[3]);
10853         size += rsurface.array_size * sizeof(float[3]);
10854         size += rsurface.array_size * sizeof(float[3]);
10855         size += rsurface.array_size * sizeof(float[3]);
10856         size += rsurface.array_size * sizeof(float[3]);
10857         size += rsurface.array_size * sizeof(float[3]);
10858         size += rsurface.array_size * sizeof(float[4]);
10859         size += rsurface.array_size * sizeof(float[2]);
10860         size += rsurface.array_size * sizeof(float[2]);
10861         size += rsurface.array_size * sizeof(float[4]);
10862         size += rsurface.array_size * sizeof(int[3]);
10863         size += rsurface.array_size * sizeof(unsigned short[3]);
10864         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10865         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10866         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10867         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10868         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10869         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10870         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10871         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10872         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10873         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10874         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10875         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10876         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10877         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10878         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10879         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10880         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10881         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10882         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10883 }
10884
10885 void RSurf_ActiveWorldEntity(void)
10886 {
10887         int newvertices;
10888         dp_model_t *model = r_refdef.scene.worldmodel;
10889         //if (rsurface.entity == r_refdef.scene.worldentity)
10890         //      return;
10891         rsurface.entity = r_refdef.scene.worldentity;
10892         rsurface.skeleton = NULL;
10893         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10894         rsurface.ent_skinnum = 0;
10895         rsurface.ent_qwskin = -1;
10896         rsurface.ent_shadertime = 0;
10897         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10898         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10899         if (rsurface.array_size < newvertices)
10900                 R_Mesh_ResizeArrays(newvertices);
10901         rsurface.matrix = identitymatrix;
10902         rsurface.inversematrix = identitymatrix;
10903         rsurface.matrixscale = 1;
10904         rsurface.inversematrixscale = 1;
10905         R_EntityMatrix(&identitymatrix);
10906         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10907         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10908         rsurface.fograngerecip = r_refdef.fograngerecip;
10909         rsurface.fogheightfade = r_refdef.fogheightfade;
10910         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10911         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10912         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10913         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10914         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10915         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10916         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10917         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10918         rsurface.colormod[3] = 1;
10919         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);
10920         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10921         rsurface.frameblend[0].lerp = 1;
10922         rsurface.ent_alttextures = false;
10923         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10924         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10925         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10926         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10927         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10928         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10929         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10930         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10931         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10932         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10933         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10934         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10935         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10936         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10937         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10938         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10939         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10940         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10941         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10942         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10943         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10944         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10945         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10946         rsurface.modelelement3i = model->surfmesh.data_element3i;
10947         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10948         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10949         rsurface.modelelement3s = model->surfmesh.data_element3s;
10950         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10951         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10952         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10953         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10954         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10955         rsurface.modelsurfaces = model->data_surfaces;
10956         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10957         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10958         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10959         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10960         rsurface.modelgeneratedvertex = false;
10961         rsurface.batchgeneratedvertex = false;
10962         rsurface.batchfirstvertex = 0;
10963         rsurface.batchnumvertices = 0;
10964         rsurface.batchfirsttriangle = 0;
10965         rsurface.batchnumtriangles = 0;
10966         rsurface.batchvertex3f  = NULL;
10967         rsurface.batchvertex3f_vertexbuffer = NULL;
10968         rsurface.batchvertex3f_bufferoffset = 0;
10969         rsurface.batchsvector3f = NULL;
10970         rsurface.batchsvector3f_vertexbuffer = NULL;
10971         rsurface.batchsvector3f_bufferoffset = 0;
10972         rsurface.batchtvector3f = NULL;
10973         rsurface.batchtvector3f_vertexbuffer = NULL;
10974         rsurface.batchtvector3f_bufferoffset = 0;
10975         rsurface.batchnormal3f  = NULL;
10976         rsurface.batchnormal3f_vertexbuffer = NULL;
10977         rsurface.batchnormal3f_bufferoffset = 0;
10978         rsurface.batchlightmapcolor4f = NULL;
10979         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10980         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10981         rsurface.batchtexcoordtexture2f = NULL;
10982         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10983         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10984         rsurface.batchtexcoordlightmap2f = NULL;
10985         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10986         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10987         rsurface.batchvertexmesh = NULL;
10988         rsurface.batchvertexmeshbuffer = NULL;
10989         rsurface.batchvertexposition = NULL;
10990         rsurface.batchvertexpositionbuffer = NULL;
10991         rsurface.batchelement3i = NULL;
10992         rsurface.batchelement3i_indexbuffer = NULL;
10993         rsurface.batchelement3i_bufferoffset = 0;
10994         rsurface.batchelement3s = NULL;
10995         rsurface.batchelement3s_indexbuffer = NULL;
10996         rsurface.batchelement3s_bufferoffset = 0;
10997         rsurface.passcolor4f = NULL;
10998         rsurface.passcolor4f_vertexbuffer = NULL;
10999         rsurface.passcolor4f_bufferoffset = 0;
11000 }
11001
11002 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11003 {
11004         int newvertices;
11005         dp_model_t *model = ent->model;
11006         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11007         //      return;
11008         rsurface.entity = (entity_render_t *)ent;
11009         rsurface.skeleton = ent->skeleton;
11010         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11011         rsurface.ent_skinnum = ent->skinnum;
11012         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;
11013         rsurface.ent_shadertime = ent->shadertime;
11014         rsurface.ent_flags = ent->flags;
11015         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
11016         if (rsurface.array_size < newvertices)
11017                 R_Mesh_ResizeArrays(newvertices);
11018         rsurface.matrix = ent->matrix;
11019         rsurface.inversematrix = ent->inversematrix;
11020         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11021         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11022         R_EntityMatrix(&rsurface.matrix);
11023         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11024         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11025         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11026         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11027         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11028         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11029         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11030         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11031         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11032         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11033         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11034         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11035         rsurface.colormod[3] = ent->alpha;
11036         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11037         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11038         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11039         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11040         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11041         if (ent->model->brush.submodel && !prepass)
11042         {
11043                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11044                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11045         }
11046         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11047         {
11048                 if (ent->animcache_vertex3f && !r_framedata_failed)
11049                 {
11050                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11051                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11052                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11053                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11054                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11055                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11056                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11057                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11058                 }
11059                 else if (wanttangents)
11060                 {
11061                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11062                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11063                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11064                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11065                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11066                         rsurface.modelvertexmesh = NULL;
11067                         rsurface.modelvertexmeshbuffer = NULL;
11068                         rsurface.modelvertexposition = NULL;
11069                         rsurface.modelvertexpositionbuffer = NULL;
11070                 }
11071                 else if (wantnormals)
11072                 {
11073                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11074                         rsurface.modelsvector3f = NULL;
11075                         rsurface.modeltvector3f = NULL;
11076                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11077                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11078                         rsurface.modelvertexmesh = NULL;
11079                         rsurface.modelvertexmeshbuffer = NULL;
11080                         rsurface.modelvertexposition = NULL;
11081                         rsurface.modelvertexpositionbuffer = NULL;
11082                 }
11083                 else
11084                 {
11085                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11086                         rsurface.modelsvector3f = NULL;
11087                         rsurface.modeltvector3f = NULL;
11088                         rsurface.modelnormal3f = NULL;
11089                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11090                         rsurface.modelvertexmesh = NULL;
11091                         rsurface.modelvertexmeshbuffer = NULL;
11092                         rsurface.modelvertexposition = NULL;
11093                         rsurface.modelvertexpositionbuffer = NULL;
11094                 }
11095                 rsurface.modelvertex3f_vertexbuffer = 0;
11096                 rsurface.modelvertex3f_bufferoffset = 0;
11097                 rsurface.modelsvector3f_vertexbuffer = 0;
11098                 rsurface.modelsvector3f_bufferoffset = 0;
11099                 rsurface.modeltvector3f_vertexbuffer = 0;
11100                 rsurface.modeltvector3f_bufferoffset = 0;
11101                 rsurface.modelnormal3f_vertexbuffer = 0;
11102                 rsurface.modelnormal3f_bufferoffset = 0;
11103                 rsurface.modelgeneratedvertex = true;
11104         }
11105         else
11106         {
11107                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11108                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11109                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11110                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11111                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11112                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11113                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11114                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11115                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11116                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11117                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11118                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11119                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11120                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11121                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11122                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11123                 rsurface.modelgeneratedvertex = false;
11124         }
11125         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11126         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11127         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11128         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11129         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11130         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11131         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11132         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11133         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11134         rsurface.modelelement3i = model->surfmesh.data_element3i;
11135         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11136         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11137         rsurface.modelelement3s = model->surfmesh.data_element3s;
11138         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11139         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11140         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11141         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11142         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11143         rsurface.modelsurfaces = model->data_surfaces;
11144         rsurface.batchgeneratedvertex = false;
11145         rsurface.batchfirstvertex = 0;
11146         rsurface.batchnumvertices = 0;
11147         rsurface.batchfirsttriangle = 0;
11148         rsurface.batchnumtriangles = 0;
11149         rsurface.batchvertex3f  = NULL;
11150         rsurface.batchvertex3f_vertexbuffer = NULL;
11151         rsurface.batchvertex3f_bufferoffset = 0;
11152         rsurface.batchsvector3f = NULL;
11153         rsurface.batchsvector3f_vertexbuffer = NULL;
11154         rsurface.batchsvector3f_bufferoffset = 0;
11155         rsurface.batchtvector3f = NULL;
11156         rsurface.batchtvector3f_vertexbuffer = NULL;
11157         rsurface.batchtvector3f_bufferoffset = 0;
11158         rsurface.batchnormal3f  = NULL;
11159         rsurface.batchnormal3f_vertexbuffer = NULL;
11160         rsurface.batchnormal3f_bufferoffset = 0;
11161         rsurface.batchlightmapcolor4f = NULL;
11162         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11163         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11164         rsurface.batchtexcoordtexture2f = NULL;
11165         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11166         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11167         rsurface.batchtexcoordlightmap2f = NULL;
11168         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11169         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11170         rsurface.batchvertexmesh = NULL;
11171         rsurface.batchvertexmeshbuffer = NULL;
11172         rsurface.batchvertexposition = NULL;
11173         rsurface.batchvertexpositionbuffer = NULL;
11174         rsurface.batchelement3i = NULL;
11175         rsurface.batchelement3i_indexbuffer = NULL;
11176         rsurface.batchelement3i_bufferoffset = 0;
11177         rsurface.batchelement3s = NULL;
11178         rsurface.batchelement3s_indexbuffer = NULL;
11179         rsurface.batchelement3s_bufferoffset = 0;
11180         rsurface.passcolor4f = NULL;
11181         rsurface.passcolor4f_vertexbuffer = NULL;
11182         rsurface.passcolor4f_bufferoffset = 0;
11183 }
11184
11185 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)
11186 {
11187         int newvertices;
11188
11189         rsurface.entity = r_refdef.scene.worldentity;
11190         rsurface.skeleton = NULL;
11191         rsurface.ent_skinnum = 0;
11192         rsurface.ent_qwskin = -1;
11193         rsurface.ent_shadertime = shadertime;
11194         rsurface.ent_flags = entflags;
11195         rsurface.modelnumvertices = numvertices;
11196         rsurface.modelnumtriangles = numtriangles;
11197         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11198         if (rsurface.array_size < newvertices)
11199                 R_Mesh_ResizeArrays(newvertices);
11200         rsurface.matrix = *matrix;
11201         rsurface.inversematrix = *inversematrix;
11202         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11203         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11204         R_EntityMatrix(&rsurface.matrix);
11205         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11206         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11207         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11208         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11209         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11210         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11211         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11212         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11213         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11214         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11215         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11216         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11217         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);
11218         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11219         rsurface.frameblend[0].lerp = 1;
11220         rsurface.ent_alttextures = false;
11221         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11222         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11223         if (wanttangents)
11224         {
11225                 rsurface.modelvertex3f = vertex3f;
11226                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11227                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11228                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11229         }
11230         else if (wantnormals)
11231         {
11232                 rsurface.modelvertex3f = vertex3f;
11233                 rsurface.modelsvector3f = NULL;
11234                 rsurface.modeltvector3f = NULL;
11235                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11236         }
11237         else
11238         {
11239                 rsurface.modelvertex3f = vertex3f;
11240                 rsurface.modelsvector3f = NULL;
11241                 rsurface.modeltvector3f = NULL;
11242                 rsurface.modelnormal3f = NULL;
11243         }
11244         rsurface.modelvertexmesh = NULL;
11245         rsurface.modelvertexmeshbuffer = NULL;
11246         rsurface.modelvertexposition = NULL;
11247         rsurface.modelvertexpositionbuffer = NULL;
11248         rsurface.modelvertex3f_vertexbuffer = 0;
11249         rsurface.modelvertex3f_bufferoffset = 0;
11250         rsurface.modelsvector3f_vertexbuffer = 0;
11251         rsurface.modelsvector3f_bufferoffset = 0;
11252         rsurface.modeltvector3f_vertexbuffer = 0;
11253         rsurface.modeltvector3f_bufferoffset = 0;
11254         rsurface.modelnormal3f_vertexbuffer = 0;
11255         rsurface.modelnormal3f_bufferoffset = 0;
11256         rsurface.modelgeneratedvertex = true;
11257         rsurface.modellightmapcolor4f  = color4f;
11258         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11259         rsurface.modellightmapcolor4f_bufferoffset = 0;
11260         rsurface.modeltexcoordtexture2f  = texcoord2f;
11261         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11262         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11263         rsurface.modeltexcoordlightmap2f  = NULL;
11264         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11265         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11266         rsurface.modelelement3i = element3i;
11267         rsurface.modelelement3i_indexbuffer = NULL;
11268         rsurface.modelelement3i_bufferoffset = 0;
11269         rsurface.modelelement3s = element3s;
11270         rsurface.modelelement3s_indexbuffer = NULL;
11271         rsurface.modelelement3s_bufferoffset = 0;
11272         rsurface.modellightmapoffsets = NULL;
11273         rsurface.modelsurfaces = NULL;
11274         rsurface.batchgeneratedvertex = false;
11275         rsurface.batchfirstvertex = 0;
11276         rsurface.batchnumvertices = 0;
11277         rsurface.batchfirsttriangle = 0;
11278         rsurface.batchnumtriangles = 0;
11279         rsurface.batchvertex3f  = NULL;
11280         rsurface.batchvertex3f_vertexbuffer = NULL;
11281         rsurface.batchvertex3f_bufferoffset = 0;
11282         rsurface.batchsvector3f = NULL;
11283         rsurface.batchsvector3f_vertexbuffer = NULL;
11284         rsurface.batchsvector3f_bufferoffset = 0;
11285         rsurface.batchtvector3f = NULL;
11286         rsurface.batchtvector3f_vertexbuffer = NULL;
11287         rsurface.batchtvector3f_bufferoffset = 0;
11288         rsurface.batchnormal3f  = NULL;
11289         rsurface.batchnormal3f_vertexbuffer = NULL;
11290         rsurface.batchnormal3f_bufferoffset = 0;
11291         rsurface.batchlightmapcolor4f = NULL;
11292         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11293         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11294         rsurface.batchtexcoordtexture2f = NULL;
11295         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11296         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11297         rsurface.batchtexcoordlightmap2f = NULL;
11298         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11299         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11300         rsurface.batchvertexmesh = NULL;
11301         rsurface.batchvertexmeshbuffer = NULL;
11302         rsurface.batchvertexposition = NULL;
11303         rsurface.batchvertexpositionbuffer = NULL;
11304         rsurface.batchelement3i = NULL;
11305         rsurface.batchelement3i_indexbuffer = NULL;
11306         rsurface.batchelement3i_bufferoffset = 0;
11307         rsurface.batchelement3s = NULL;
11308         rsurface.batchelement3s_indexbuffer = NULL;
11309         rsurface.batchelement3s_bufferoffset = 0;
11310         rsurface.passcolor4f = NULL;
11311         rsurface.passcolor4f_vertexbuffer = NULL;
11312         rsurface.passcolor4f_bufferoffset = 0;
11313
11314         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11315         {
11316                 if ((wantnormals || wanttangents) && !normal3f)
11317                 {
11318                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11319                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11320                 }
11321                 if (wanttangents && !svector3f)
11322                 {
11323                         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);
11324                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11325                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11326                 }
11327         }
11328 }
11329
11330 float RSurf_FogPoint(const float *v)
11331 {
11332         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11333         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11334         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11335         float FogHeightFade = r_refdef.fogheightfade;
11336         float fogfrac;
11337         unsigned int fogmasktableindex;
11338         if (r_refdef.fogplaneviewabove)
11339                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11340         else
11341                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11342         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11343         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11344 }
11345
11346 float RSurf_FogVertex(const float *v)
11347 {
11348         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11349         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11350         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11351         float FogHeightFade = rsurface.fogheightfade;
11352         float fogfrac;
11353         unsigned int fogmasktableindex;
11354         if (r_refdef.fogplaneviewabove)
11355                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11356         else
11357                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11358         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11359         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11360 }
11361
11362 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11363 {
11364         int i;
11365         for (i = 0;i < numelements;i++)
11366                 outelement3i[i] = inelement3i[i] + adjust;
11367 }
11368
11369 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11370 extern cvar_t gl_vbo;
11371 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11372 {
11373         int deformindex;
11374         int firsttriangle;
11375         int numtriangles;
11376         int firstvertex;
11377         int endvertex;
11378         int numvertices;
11379         int surfacefirsttriangle;
11380         int surfacenumtriangles;
11381         int surfacefirstvertex;
11382         int surfaceendvertex;
11383         int surfacenumvertices;
11384         int needsupdate;
11385         int i, j;
11386         qboolean gaps;
11387         qboolean dynamicvertex;
11388         float amplitude;
11389         float animpos;
11390         float scale;
11391         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11392         float waveparms[4];
11393         q3shaderinfo_deform_t *deform;
11394         const msurface_t *surface, *firstsurface;
11395         r_vertexposition_t *vertexposition;
11396         r_vertexmesh_t *vertexmesh;
11397         if (!texturenumsurfaces)
11398                 return;
11399         // find vertex range of this surface batch
11400         gaps = false;
11401         firstsurface = texturesurfacelist[0];
11402         firsttriangle = firstsurface->num_firsttriangle;
11403         numtriangles = 0;
11404         firstvertex = endvertex = firstsurface->num_firstvertex;
11405         for (i = 0;i < texturenumsurfaces;i++)
11406         {
11407                 surface = texturesurfacelist[i];
11408                 if (surface != firstsurface + i)
11409                         gaps = true;
11410                 surfacefirstvertex = surface->num_firstvertex;
11411                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11412                 surfacenumtriangles = surface->num_triangles;
11413                 if (firstvertex > surfacefirstvertex)
11414                         firstvertex = surfacefirstvertex;
11415                 if (endvertex < surfaceendvertex)
11416                         endvertex = surfaceendvertex;
11417                 numtriangles += surfacenumtriangles;
11418         }
11419
11420         // we now know the vertex range used, and if there are any gaps in it
11421         rsurface.batchfirstvertex = firstvertex;
11422         rsurface.batchnumvertices = endvertex - firstvertex;
11423         rsurface.batchfirsttriangle = firsttriangle;
11424         rsurface.batchnumtriangles = numtriangles;
11425
11426         // this variable holds flags for which properties have been updated that
11427         // may require regenerating vertexmesh or vertexposition arrays...
11428         needsupdate = 0;
11429
11430         // check if any dynamic vertex processing must occur
11431         dynamicvertex = false;
11432
11433         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11434                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11435         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11436         {
11437                 switch (deform->deform)
11438                 {
11439                 default:
11440                 case Q3DEFORM_PROJECTIONSHADOW:
11441                 case Q3DEFORM_TEXT0:
11442                 case Q3DEFORM_TEXT1:
11443                 case Q3DEFORM_TEXT2:
11444                 case Q3DEFORM_TEXT3:
11445                 case Q3DEFORM_TEXT4:
11446                 case Q3DEFORM_TEXT5:
11447                 case Q3DEFORM_TEXT6:
11448                 case Q3DEFORM_TEXT7:
11449                 case Q3DEFORM_NONE:
11450                         break;
11451                 case Q3DEFORM_AUTOSPRITE:
11452                         dynamicvertex = true;
11453                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11454                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11455                         break;
11456                 case Q3DEFORM_AUTOSPRITE2:
11457                         dynamicvertex = true;
11458                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11459                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11460                         break;
11461                 case Q3DEFORM_NORMAL:
11462                         dynamicvertex = true;
11463                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11464                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11465                         break;
11466                 case Q3DEFORM_WAVE:
11467                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11468                                 break; // if wavefunc is a nop, ignore this transform
11469                         dynamicvertex = true;
11470                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11471                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11472                         break;
11473                 case Q3DEFORM_BULGE:
11474                         dynamicvertex = true;
11475                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11476                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11477                         break;
11478                 case Q3DEFORM_MOVE:
11479                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11480                                 break; // if wavefunc is a nop, ignore this transform
11481                         dynamicvertex = true;
11482                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11483                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11484                         break;
11485                 }
11486         }
11487         switch(rsurface.texture->tcgen.tcgen)
11488         {
11489         default:
11490         case Q3TCGEN_TEXTURE:
11491                 break;
11492         case Q3TCGEN_LIGHTMAP:
11493                 dynamicvertex = true;
11494                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11495                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11496                 break;
11497         case Q3TCGEN_VECTOR:
11498                 dynamicvertex = true;
11499                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11500                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11501                 break;
11502         case Q3TCGEN_ENVIRONMENT:
11503                 dynamicvertex = true;
11504                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11505                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11506                 break;
11507         }
11508         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11509         {
11510                 dynamicvertex = true;
11511                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11512                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11513         }
11514
11515         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11516         {
11517                 dynamicvertex = true;
11518                 batchneed |= BATCHNEED_NOGAPS;
11519                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11520         }
11521
11522         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11523         {
11524                 dynamicvertex = true;
11525                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11526                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11527         }
11528
11529         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11530         {
11531                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11532                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11533                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11534                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11535                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11536                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11537                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11538         }
11539
11540         // when the model data has no vertex buffer (dynamic mesh), we need to
11541         // eliminate gaps
11542         if (!rsurface.modelvertexmeshbuffer)
11543                 batchneed |= BATCHNEED_NOGAPS;
11544
11545         // if needsupdate, we have to do a dynamic vertex batch for sure
11546         if (needsupdate & batchneed)
11547                 dynamicvertex = true;
11548
11549         // see if we need to build vertexmesh from arrays
11550         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11551                 dynamicvertex = true;
11552
11553         // see if we need to build vertexposition from arrays
11554         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11555                 dynamicvertex = true;
11556
11557         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11558         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11559                 dynamicvertex = true;
11560
11561         // if there is a chance of animated vertex colors, it's a dynamic batch
11562         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11563                 dynamicvertex = true;
11564
11565         rsurface.batchvertex3f = rsurface.modelvertex3f;
11566         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11567         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11568         rsurface.batchsvector3f = rsurface.modelsvector3f;
11569         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11570         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11571         rsurface.batchtvector3f = rsurface.modeltvector3f;
11572         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11573         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11574         rsurface.batchnormal3f = rsurface.modelnormal3f;
11575         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11576         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11577         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11578         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11579         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11580         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11581         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11582         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11583         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11584         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11585         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11586         rsurface.batchvertexposition = rsurface.modelvertexposition;
11587         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11588         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11589         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11590         rsurface.batchelement3i = rsurface.modelelement3i;
11591         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11592         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11593         rsurface.batchelement3s = rsurface.modelelement3s;
11594         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11595         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11596
11597         // if any dynamic vertex processing has to occur in software, we copy the
11598         // entire surface list together before processing to rebase the vertices
11599         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11600         //
11601         // if any gaps exist and we do not have a static vertex buffer, we have to
11602         // copy the surface list together to avoid wasting upload bandwidth on the
11603         // vertices in the gaps.
11604         //
11605         // if gaps exist and we have a static vertex buffer, we still have to
11606         // combine the index buffer ranges into one dynamic index buffer.
11607         //
11608         // in all cases we end up with data that can be drawn in one call.
11609
11610         if (!dynamicvertex)
11611         {
11612                 // static vertex data, just set pointers...
11613                 rsurface.batchgeneratedvertex = false;
11614                 // if there are gaps, we want to build a combined index buffer,
11615                 // otherwise use the original static buffer with an appropriate offset
11616                 if (gaps)
11617                 {
11618                         firsttriangle = 0;
11619                         numtriangles = 0;
11620                         for (i = 0;i < texturenumsurfaces;i++)
11621                         {
11622                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11623                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11624                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11625                                 numtriangles += surfacenumtriangles;
11626                         }
11627                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11628                         rsurface.batchelement3i_indexbuffer = NULL;
11629                         rsurface.batchelement3i_bufferoffset = 0;
11630                         rsurface.batchelement3s = NULL;
11631                         rsurface.batchelement3s_indexbuffer = NULL;
11632                         rsurface.batchelement3s_bufferoffset = 0;
11633                         if (endvertex <= 65536)
11634                         {
11635                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11636                                 for (i = 0;i < numtriangles*3;i++)
11637                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11638                         }
11639                         rsurface.batchfirsttriangle = firsttriangle;
11640                         rsurface.batchnumtriangles = numtriangles;
11641                 }
11642                 return;
11643         }
11644
11645         // something needs software processing, do it for real...
11646         // we only directly handle interleaved array data in this case...
11647         rsurface.batchgeneratedvertex = true;
11648
11649         // now copy the vertex data into a combined array and make an index array
11650         // (this is what Quake3 does all the time)
11651         //if (gaps || rsurface.batchfirstvertex)
11652         {
11653                 rsurface.batchvertexposition = NULL;
11654                 rsurface.batchvertexpositionbuffer = NULL;
11655                 rsurface.batchvertexmesh = NULL;
11656                 rsurface.batchvertexmeshbuffer = NULL;
11657                 rsurface.batchvertex3f = NULL;
11658                 rsurface.batchvertex3f_vertexbuffer = NULL;
11659                 rsurface.batchvertex3f_bufferoffset = 0;
11660                 rsurface.batchsvector3f = NULL;
11661                 rsurface.batchsvector3f_vertexbuffer = NULL;
11662                 rsurface.batchsvector3f_bufferoffset = 0;
11663                 rsurface.batchtvector3f = NULL;
11664                 rsurface.batchtvector3f_vertexbuffer = NULL;
11665                 rsurface.batchtvector3f_bufferoffset = 0;
11666                 rsurface.batchnormal3f = NULL;
11667                 rsurface.batchnormal3f_vertexbuffer = NULL;
11668                 rsurface.batchnormal3f_bufferoffset = 0;
11669                 rsurface.batchlightmapcolor4f = NULL;
11670                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11671                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11672                 rsurface.batchtexcoordtexture2f = NULL;
11673                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11674                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11675                 rsurface.batchtexcoordlightmap2f = NULL;
11676                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11677                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11678                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11679                 rsurface.batchelement3i_indexbuffer = NULL;
11680                 rsurface.batchelement3i_bufferoffset = 0;
11681                 rsurface.batchelement3s = NULL;
11682                 rsurface.batchelement3s_indexbuffer = NULL;
11683                 rsurface.batchelement3s_bufferoffset = 0;
11684                 // we'll only be setting up certain arrays as needed
11685                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11686                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11687                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11688                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11689                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11690                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11691                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11692                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11693                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11694                 {
11695                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11696                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11697                 }
11698                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11699                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11700                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11701                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11702                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11703                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11704                 numvertices = 0;
11705                 numtriangles = 0;
11706                 for (i = 0;i < texturenumsurfaces;i++)
11707                 {
11708                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11709                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11710                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11711                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11712                         // copy only the data requested
11713                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11714                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11715                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11716                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11717                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11718                         {
11719                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11720                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11721                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11722                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11723                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11724                                 {
11725                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11726                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11727                                 }
11728                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11729                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11730                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11731                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11732                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11733                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11734                         }
11735                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11736                         numvertices += surfacenumvertices;
11737                         numtriangles += surfacenumtriangles;
11738                 }
11739
11740                 // generate a 16bit index array as well if possible
11741                 // (in general, dynamic batches fit)
11742                 if (numvertices <= 65536)
11743                 {
11744                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11745                         for (i = 0;i < numtriangles*3;i++)
11746                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11747                 }
11748
11749                 // since we've copied everything, the batch now starts at 0
11750                 rsurface.batchfirstvertex = 0;
11751                 rsurface.batchnumvertices = numvertices;
11752                 rsurface.batchfirsttriangle = 0;
11753                 rsurface.batchnumtriangles = numtriangles;
11754         }
11755
11756         // q1bsp surfaces rendered in vertex color mode have to have colors
11757         // calculated based on lightstyles
11758         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11759         {
11760                 // generate color arrays for the surfaces in this list
11761                 int c[4];
11762                 int scale;
11763                 int size3;
11764                 const int *offsets;
11765                 const unsigned char *lm;
11766                 numvertices = 0;
11767                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11768                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11769                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11770                 for (i = 0;i < texturenumsurfaces;i++)
11771                 {
11772                         surface = texturesurfacelist[i];
11773                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11774                         surfacenumvertices = surface->num_vertices;
11775                         if (surface->lightmapinfo->samples)
11776                         {
11777                                 for (j = 0;j < surfacenumvertices;j++)
11778                                 {
11779                                         lm = surface->lightmapinfo->samples + offsets[j];
11780                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11781                                         VectorScale(lm, scale, c);
11782                                         if (surface->lightmapinfo->styles[1] != 255)
11783                                         {
11784                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11785                                                 lm += size3;
11786                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11787                                                 VectorMA(c, scale, lm, c);
11788                                                 if (surface->lightmapinfo->styles[2] != 255)
11789                                                 {
11790                                                         lm += size3;
11791                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11792                                                         VectorMA(c, scale, lm, c);
11793                                                         if (surface->lightmapinfo->styles[3] != 255)
11794                                                         {
11795                                                                 lm += size3;
11796                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11797                                                                 VectorMA(c, scale, lm, c);
11798                                                         }
11799                                                 }
11800                                         }
11801                                         c[0] >>= 15;
11802                                         c[1] >>= 15;
11803                                         c[2] >>= 15;
11804                                         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);
11805                                         numvertices++;
11806                                 }
11807                         }
11808                         else
11809                         {
11810                                 for (j = 0;j < surfacenumvertices;j++)
11811                                 {
11812                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11813                                         numvertices++;
11814                                 }
11815                         }
11816                 }
11817         }
11818
11819         // if vertices are deformed (sprite flares and things in maps, possibly
11820         // water waves, bulges and other deformations), modify the copied vertices
11821         // in place
11822         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11823         {
11824                 switch (deform->deform)
11825                 {
11826                 default:
11827                 case Q3DEFORM_PROJECTIONSHADOW:
11828                 case Q3DEFORM_TEXT0:
11829                 case Q3DEFORM_TEXT1:
11830                 case Q3DEFORM_TEXT2:
11831                 case Q3DEFORM_TEXT3:
11832                 case Q3DEFORM_TEXT4:
11833                 case Q3DEFORM_TEXT5:
11834                 case Q3DEFORM_TEXT6:
11835                 case Q3DEFORM_TEXT7:
11836                 case Q3DEFORM_NONE:
11837                         break;
11838                 case Q3DEFORM_AUTOSPRITE:
11839                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11840                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11841                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11842                         VectorNormalize(newforward);
11843                         VectorNormalize(newright);
11844                         VectorNormalize(newup);
11845                         // a single autosprite surface can contain multiple sprites...
11846                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11847                         {
11848                                 VectorClear(center);
11849                                 for (i = 0;i < 4;i++)
11850                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11851                                 VectorScale(center, 0.25f, center);
11852                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11853                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11854                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11855                                 for (i = 0;i < 4;i++)
11856                                 {
11857                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11858                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11859                                 }
11860                         }
11861                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11862                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11863                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11864                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11865                         rsurface.batchvertex3f_vertexbuffer = NULL;
11866                         rsurface.batchvertex3f_bufferoffset = 0;
11867                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11868                         rsurface.batchsvector3f_vertexbuffer = NULL;
11869                         rsurface.batchsvector3f_bufferoffset = 0;
11870                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11871                         rsurface.batchtvector3f_vertexbuffer = NULL;
11872                         rsurface.batchtvector3f_bufferoffset = 0;
11873                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11874                         rsurface.batchnormal3f_vertexbuffer = NULL;
11875                         rsurface.batchnormal3f_bufferoffset = 0;
11876                         break;
11877                 case Q3DEFORM_AUTOSPRITE2:
11878                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11879                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11880                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11881                         VectorNormalize(newforward);
11882                         VectorNormalize(newright);
11883                         VectorNormalize(newup);
11884                         {
11885                                 const float *v1, *v2;
11886                                 vec3_t start, end;
11887                                 float f, l;
11888                                 struct
11889                                 {
11890                                         float length2;
11891                                         const float *v1;
11892                                         const float *v2;
11893                                 }
11894                                 shortest[2];
11895                                 memset(shortest, 0, sizeof(shortest));
11896                                 // a single autosprite surface can contain multiple sprites...
11897                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11898                                 {
11899                                         VectorClear(center);
11900                                         for (i = 0;i < 4;i++)
11901                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11902                                         VectorScale(center, 0.25f, center);
11903                                         // find the two shortest edges, then use them to define the
11904                                         // axis vectors for rotating around the central axis
11905                                         for (i = 0;i < 6;i++)
11906                                         {
11907                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11908                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11909                                                 l = VectorDistance2(v1, v2);
11910                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11911                                                 if (v1[2] != v2[2])
11912                                                         l += (1.0f / 1024.0f);
11913                                                 if (shortest[0].length2 > l || i == 0)
11914                                                 {
11915                                                         shortest[1] = shortest[0];
11916                                                         shortest[0].length2 = l;
11917                                                         shortest[0].v1 = v1;
11918                                                         shortest[0].v2 = v2;
11919                                                 }
11920                                                 else if (shortest[1].length2 > l || i == 1)
11921                                                 {
11922                                                         shortest[1].length2 = l;
11923                                                         shortest[1].v1 = v1;
11924                                                         shortest[1].v2 = v2;
11925                                                 }
11926                                         }
11927                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11928                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11929                                         // this calculates the right vector from the shortest edge
11930                                         // and the up vector from the edge midpoints
11931                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11932                                         VectorNormalize(right);
11933                                         VectorSubtract(end, start, up);
11934                                         VectorNormalize(up);
11935                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11936                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11937                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11938                                         VectorNegate(forward, forward);
11939                                         VectorReflect(forward, 0, up, forward);
11940                                         VectorNormalize(forward);
11941                                         CrossProduct(up, forward, newright);
11942                                         VectorNormalize(newright);
11943                                         // rotate the quad around the up axis vector, this is made
11944                                         // especially easy by the fact we know the quad is flat,
11945                                         // so we only have to subtract the center position and
11946                                         // measure distance along the right vector, and then
11947                                         // multiply that by the newright vector and add back the
11948                                         // center position
11949                                         // we also need to subtract the old position to undo the
11950                                         // displacement from the center, which we do with a
11951                                         // DotProduct, the subtraction/addition of center is also
11952                                         // optimized into DotProducts here
11953                                         l = DotProduct(right, center);
11954                                         for (i = 0;i < 4;i++)
11955                                         {
11956                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11957                                                 f = DotProduct(right, v1) - l;
11958                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11959                                         }
11960                                 }
11961                         }
11962                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11963                         rsurface.batchvertex3f_vertexbuffer = NULL;
11964                         rsurface.batchvertex3f_bufferoffset = 0;
11965                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11966                         {
11967                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11968                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11969                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11970                                 rsurface.batchnormal3f_bufferoffset = 0;
11971                         }
11972                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11973                         {
11974                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11975                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11976                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11977                                 rsurface.batchsvector3f_bufferoffset = 0;
11978                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11979                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11980                                 rsurface.batchtvector3f_bufferoffset = 0;
11981                         }
11982                         break;
11983                 case Q3DEFORM_NORMAL:
11984                         // deform the normals to make reflections wavey
11985                         for (j = 0;j < rsurface.batchnumvertices;j++)
11986                         {
11987                                 float vertex[3];
11988                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11989                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11990                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11991                                 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]);
11992                                 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]);
11993                                 VectorNormalize(normal);
11994                         }
11995                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11996                         rsurface.batchnormal3f_vertexbuffer = NULL;
11997                         rsurface.batchnormal3f_bufferoffset = 0;
11998                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11999                         {
12000                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12001                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12002                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12003                                 rsurface.batchsvector3f_bufferoffset = 0;
12004                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12005                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12006                                 rsurface.batchtvector3f_bufferoffset = 0;
12007                         }
12008                         break;
12009                 case Q3DEFORM_WAVE:
12010                         // deform vertex array to make wavey water and flags and such
12011                         waveparms[0] = deform->waveparms[0];
12012                         waveparms[1] = deform->waveparms[1];
12013                         waveparms[2] = deform->waveparms[2];
12014                         waveparms[3] = deform->waveparms[3];
12015                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12016                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12017                         // this is how a divisor of vertex influence on deformation
12018                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12019                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12020                         for (j = 0;j < rsurface.batchnumvertices;j++)
12021                         {
12022                                 // if the wavefunc depends on time, evaluate it per-vertex
12023                                 if (waveparms[3])
12024                                 {
12025                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12026                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12027                                 }
12028                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12029                         }
12030                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12031                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12032                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12033                         rsurface.batchvertex3f_vertexbuffer = NULL;
12034                         rsurface.batchvertex3f_bufferoffset = 0;
12035                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12036                         rsurface.batchnormal3f_vertexbuffer = NULL;
12037                         rsurface.batchnormal3f_bufferoffset = 0;
12038                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12039                         {
12040                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12041                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12042                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12043                                 rsurface.batchsvector3f_bufferoffset = 0;
12044                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12045                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12046                                 rsurface.batchtvector3f_bufferoffset = 0;
12047                         }
12048                         break;
12049                 case Q3DEFORM_BULGE:
12050                         // deform vertex array to make the surface have moving bulges
12051                         for (j = 0;j < rsurface.batchnumvertices;j++)
12052                         {
12053                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12054                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12055                         }
12056                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12057                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12058                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12059                         rsurface.batchvertex3f_vertexbuffer = NULL;
12060                         rsurface.batchvertex3f_bufferoffset = 0;
12061                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12062                         rsurface.batchnormal3f_vertexbuffer = NULL;
12063                         rsurface.batchnormal3f_bufferoffset = 0;
12064                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12065                         {
12066                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12067                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12068                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12069                                 rsurface.batchsvector3f_bufferoffset = 0;
12070                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12071                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12072                                 rsurface.batchtvector3f_bufferoffset = 0;
12073                         }
12074                         break;
12075                 case Q3DEFORM_MOVE:
12076                         // deform vertex array
12077                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12078                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12079                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12080                         VectorScale(deform->parms, scale, waveparms);
12081                         for (j = 0;j < rsurface.batchnumvertices;j++)
12082                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12083                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12084                         rsurface.batchvertex3f_vertexbuffer = NULL;
12085                         rsurface.batchvertex3f_bufferoffset = 0;
12086                         break;
12087                 }
12088         }
12089
12090         // generate texcoords based on the chosen texcoord source
12091         switch(rsurface.texture->tcgen.tcgen)
12092         {
12093         default:
12094         case Q3TCGEN_TEXTURE:
12095                 break;
12096         case Q3TCGEN_LIGHTMAP:
12097                 if (rsurface.batchtexcoordlightmap2f)
12098                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12099                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12100                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12101                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12102                 break;
12103         case Q3TCGEN_VECTOR:
12104                 for (j = 0;j < rsurface.batchnumvertices;j++)
12105                 {
12106                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12107                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12108                 }
12109                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12110                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12111                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12112                 break;
12113         case Q3TCGEN_ENVIRONMENT:
12114                 // make environment reflections using a spheremap
12115                 for (j = 0;j < rsurface.batchnumvertices;j++)
12116                 {
12117                         // identical to Q3A's method, but executed in worldspace so
12118                         // carried models can be shiny too
12119
12120                         float viewer[3], d, reflected[3], worldreflected[3];
12121
12122                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12123                         // VectorNormalize(viewer);
12124
12125                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12126
12127                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12128                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12129                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12130                         // note: this is proportinal to viewer, so we can normalize later
12131
12132                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12133                         VectorNormalize(worldreflected);
12134
12135                         // note: this sphere map only uses world x and z!
12136                         // so positive and negative y will LOOK THE SAME.
12137                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12138                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12139                 }
12140                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12141                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12142                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12143                 break;
12144         }
12145         // the only tcmod that needs software vertex processing is turbulent, so
12146         // check for it here and apply the changes if needed
12147         // and we only support that as the first one
12148         // (handling a mixture of turbulent and other tcmods would be problematic
12149         //  without punting it entirely to a software path)
12150         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12151         {
12152                 amplitude = rsurface.texture->tcmods[0].parms[1];
12153                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12154                 for (j = 0;j < rsurface.batchnumvertices;j++)
12155                 {
12156                         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);
12157                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12158                 }
12159                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12160                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12161                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12162         }
12163
12164         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12165         {
12166                 // convert the modified arrays to vertex structs
12167                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12168                 rsurface.batchvertexmeshbuffer = NULL;
12169                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12170                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12171                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12172                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12173                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12174                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12175                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12176                 {
12177                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12178                         {
12179                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12180                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12181                         }
12182                 }
12183                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12184                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12185                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12186                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12187                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12188                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12189                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12190                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12191                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12192         }
12193
12194         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12195         {
12196                 // convert the modified arrays to vertex structs
12197                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12198                 rsurface.batchvertexpositionbuffer = NULL;
12199                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12200                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12201                 else
12202                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12203                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12204         }
12205 }
12206
12207 void RSurf_DrawBatch(void)
12208 {
12209         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12210         // through the pipeline, killing it earlier in the pipeline would have
12211         // per-surface overhead rather than per-batch overhead, so it's best to
12212         // reject it here, before it hits glDraw.
12213         if (rsurface.batchnumtriangles == 0)
12214                 return;
12215 #if 0
12216         // batch debugging code
12217         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12218         {
12219                 int i;
12220                 int j;
12221                 int c;
12222                 const int *e;
12223                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12224                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12225                 {
12226                         c = e[i];
12227                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12228                         {
12229                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12230                                 {
12231                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12232                                                 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);
12233                                         break;
12234                                 }
12235                         }
12236                 }
12237         }
12238 #endif
12239         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);
12240 }
12241
12242 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12243 {
12244         // pick the closest matching water plane
12245         int planeindex, vertexindex, bestplaneindex = -1;
12246         float d, bestd;
12247         vec3_t vert;
12248         const float *v;
12249         r_waterstate_waterplane_t *p;
12250         bestd = 0;
12251         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12252         {
12253                 if(p->camera_entity != rsurface.texture->camera_entity)
12254                         continue;
12255                 d = 0;
12256                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12257                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12258                 {
12259                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12260                         d += fabs(PlaneDiff(vert, &p->plane));
12261                 }
12262                 if (bestd > d || bestplaneindex < 0)
12263                 {
12264                         bestd = d;
12265                         bestplaneindex = planeindex;
12266                 }
12267         }
12268         return bestplaneindex;
12269 }
12270
12271 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12272 {
12273         int i;
12274         for (i = 0;i < rsurface.batchnumvertices;i++)
12275                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12276         rsurface.passcolor4f = rsurface.array_passcolor4f;
12277         rsurface.passcolor4f_vertexbuffer = 0;
12278         rsurface.passcolor4f_bufferoffset = 0;
12279 }
12280
12281 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12282 {
12283         int i;
12284         float f;
12285         const float *v;
12286         const float *c;
12287         float *c2;
12288         if (rsurface.passcolor4f)
12289         {
12290                 // generate color arrays
12291                 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)
12292                 {
12293                         f = RSurf_FogVertex(v);
12294                         c2[0] = c[0] * f;
12295                         c2[1] = c[1] * f;
12296                         c2[2] = c[2] * f;
12297                         c2[3] = c[3];
12298                 }
12299         }
12300         else
12301         {
12302                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12303                 {
12304                         f = RSurf_FogVertex(v);
12305                         c2[0] = f;
12306                         c2[1] = f;
12307                         c2[2] = f;
12308                         c2[3] = 1;
12309                 }
12310         }
12311         rsurface.passcolor4f = rsurface.array_passcolor4f;
12312         rsurface.passcolor4f_vertexbuffer = 0;
12313         rsurface.passcolor4f_bufferoffset = 0;
12314 }
12315
12316 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12317 {
12318         int i;
12319         float f;
12320         const float *v;
12321         const float *c;
12322         float *c2;
12323         if (!rsurface.passcolor4f)
12324                 return;
12325         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)
12326         {
12327                 f = RSurf_FogVertex(v);
12328                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12329                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12330                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12331                 c2[3] = c[3];
12332         }
12333         rsurface.passcolor4f = rsurface.array_passcolor4f;
12334         rsurface.passcolor4f_vertexbuffer = 0;
12335         rsurface.passcolor4f_bufferoffset = 0;
12336 }
12337
12338 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12339 {
12340         int i;
12341         const float *c;
12342         float *c2;
12343         if (!rsurface.passcolor4f)
12344                 return;
12345         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12346         {
12347                 c2[0] = c[0] * r;
12348                 c2[1] = c[1] * g;
12349                 c2[2] = c[2] * b;
12350                 c2[3] = c[3] * a;
12351         }
12352         rsurface.passcolor4f = rsurface.array_passcolor4f;
12353         rsurface.passcolor4f_vertexbuffer = 0;
12354         rsurface.passcolor4f_bufferoffset = 0;
12355 }
12356
12357 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12358 {
12359         int i;
12360         const float *c;
12361         float *c2;
12362         if (!rsurface.passcolor4f)
12363                 return;
12364         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12365         {
12366                 c2[0] = c[0] + r_refdef.scene.ambient;
12367                 c2[1] = c[1] + r_refdef.scene.ambient;
12368                 c2[2] = c[2] + r_refdef.scene.ambient;
12369                 c2[3] = c[3];
12370         }
12371         rsurface.passcolor4f = rsurface.array_passcolor4f;
12372         rsurface.passcolor4f_vertexbuffer = 0;
12373         rsurface.passcolor4f_bufferoffset = 0;
12374 }
12375
12376 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12377 {
12378         // TODO: optimize
12379         rsurface.passcolor4f = NULL;
12380         rsurface.passcolor4f_vertexbuffer = 0;
12381         rsurface.passcolor4f_bufferoffset = 0;
12382         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12383         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12384         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12385         GL_Color(r, g, b, a);
12386         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12387         RSurf_DrawBatch();
12388 }
12389
12390 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12391 {
12392         // TODO: optimize applyfog && applycolor case
12393         // just apply fog if necessary, and tint the fog color array if necessary
12394         rsurface.passcolor4f = NULL;
12395         rsurface.passcolor4f_vertexbuffer = 0;
12396         rsurface.passcolor4f_bufferoffset = 0;
12397         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12398         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12399         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12400         GL_Color(r, g, b, a);
12401         RSurf_DrawBatch();
12402 }
12403
12404 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12405 {
12406         // TODO: optimize
12407         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12408         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12409         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12410         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12411         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12412         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12413         GL_Color(r, g, b, a);
12414         RSurf_DrawBatch();
12415 }
12416
12417 static void RSurf_DrawBatch_GL11_ClampColor(void)
12418 {
12419         int i;
12420         const float *c1;
12421         float *c2;
12422         if (!rsurface.passcolor4f)
12423                 return;
12424         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12425         {
12426                 c2[0] = bound(0.0f, c1[0], 1.0f);
12427                 c2[1] = bound(0.0f, c1[1], 1.0f);
12428                 c2[2] = bound(0.0f, c1[2], 1.0f);
12429                 c2[3] = bound(0.0f, c1[3], 1.0f);
12430         }
12431 }
12432
12433 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12434 {
12435         int i;
12436         float f;
12437         const float *v;
12438         const float *n;
12439         float *c;
12440         //vec3_t eyedir;
12441
12442         // fake shading
12443         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)
12444         {
12445                 f = -DotProduct(r_refdef.view.forward, n);
12446                 f = max(0, f);
12447                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12448                 f *= r_refdef.lightmapintensity;
12449                 Vector4Set(c, f, f, f, 1);
12450         }
12451
12452         rsurface.passcolor4f = rsurface.array_passcolor4f;
12453         rsurface.passcolor4f_vertexbuffer = 0;
12454         rsurface.passcolor4f_bufferoffset = 0;
12455 }
12456
12457 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12458 {
12459         RSurf_DrawBatch_GL11_ApplyFakeLight();
12460         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12461         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12462         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12463         GL_Color(r, g, b, a);
12464         RSurf_DrawBatch();
12465 }
12466
12467 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12468 {
12469         int i;
12470         float f;
12471         float alpha;
12472         const float *v;
12473         const float *n;
12474         float *c;
12475         vec3_t ambientcolor;
12476         vec3_t diffusecolor;
12477         vec3_t lightdir;
12478         // TODO: optimize
12479         // model lighting
12480         VectorCopy(rsurface.modellight_lightdir, lightdir);
12481         f = 0.5f * r_refdef.lightmapintensity;
12482         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12483         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12484         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12485         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12486         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12487         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12488         alpha = *a;
12489         if (VectorLength2(diffusecolor) > 0)
12490         {
12491                 // q3-style directional shading
12492                 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)
12493                 {
12494                         if ((f = DotProduct(n, lightdir)) > 0)
12495                                 VectorMA(ambientcolor, f, diffusecolor, c);
12496                         else
12497                                 VectorCopy(ambientcolor, c);
12498                         c[3] = alpha;
12499                 }
12500                 *r = 1;
12501                 *g = 1;
12502                 *b = 1;
12503                 *a = 1;
12504                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12505                 rsurface.passcolor4f_vertexbuffer = 0;
12506                 rsurface.passcolor4f_bufferoffset = 0;
12507                 *applycolor = false;
12508         }
12509         else
12510         {
12511                 *r = ambientcolor[0];
12512                 *g = ambientcolor[1];
12513                 *b = ambientcolor[2];
12514                 rsurface.passcolor4f = NULL;
12515                 rsurface.passcolor4f_vertexbuffer = 0;
12516                 rsurface.passcolor4f_bufferoffset = 0;
12517         }
12518 }
12519
12520 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12521 {
12522         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12523         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12524         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12525         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12526         GL_Color(r, g, b, a);
12527         RSurf_DrawBatch();
12528 }
12529
12530 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12531 {
12532         int i;
12533         float f;
12534         const float *v;
12535         float *c;
12536         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12537         {
12538                 f = 1 - RSurf_FogVertex(v);
12539                 c[0] = r;
12540                 c[1] = g;
12541                 c[2] = b;
12542                 c[3] = f * a;
12543         }
12544 }
12545
12546 void RSurf_SetupDepthAndCulling(void)
12547 {
12548         // submodels are biased to avoid z-fighting with world surfaces that they
12549         // may be exactly overlapping (avoids z-fighting artifacts on certain
12550         // doors and things in Quake maps)
12551         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12552         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12553         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12554         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12555 }
12556
12557 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12558 {
12559         // transparent sky would be ridiculous
12560         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12561                 return;
12562         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12563         skyrenderlater = true;
12564         RSurf_SetupDepthAndCulling();
12565         GL_DepthMask(true);
12566         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12567         // skymasking on them, and Quake3 never did sky masking (unlike
12568         // software Quake and software Quake2), so disable the sky masking
12569         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12570         // and skymasking also looks very bad when noclipping outside the
12571         // level, so don't use it then either.
12572         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12573         {
12574                 R_Mesh_ResetTextureState();
12575                 if (skyrendermasked)
12576                 {
12577                         R_SetupShader_DepthOrShadow();
12578                         // depth-only (masking)
12579                         GL_ColorMask(0,0,0,0);
12580                         // just to make sure that braindead drivers don't draw
12581                         // anything despite that colormask...
12582                         GL_BlendFunc(GL_ZERO, GL_ONE);
12583                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12584                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12585                 }
12586                 else
12587                 {
12588                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12589                         // fog sky
12590                         GL_BlendFunc(GL_ONE, GL_ZERO);
12591                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12592                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12593                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12594                 }
12595                 RSurf_DrawBatch();
12596                 if (skyrendermasked)
12597                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12598         }
12599         R_Mesh_ResetTextureState();
12600         GL_Color(1, 1, 1, 1);
12601 }
12602
12603 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12604 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12605 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12606 {
12607         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12608                 return;
12609         if (prepass)
12610         {
12611                 // render screenspace normalmap to texture
12612                 GL_DepthMask(true);
12613                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12614                 RSurf_DrawBatch();
12615                 return;
12616         }
12617
12618         // bind lightmap texture
12619
12620         // water/refraction/reflection/camera surfaces have to be handled specially
12621         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12622         {
12623                 int start, end, startplaneindex;
12624                 for (start = 0;start < texturenumsurfaces;start = end)
12625                 {
12626                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12627                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12628                                 ;
12629                         // now that we have a batch using the same planeindex, render it
12630                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12631                         {
12632                                 // render water or distortion background
12633                                 GL_DepthMask(true);
12634                                 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));
12635                                 RSurf_DrawBatch();
12636                                 // blend surface on top
12637                                 GL_DepthMask(false);
12638                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12639                                 RSurf_DrawBatch();
12640                         }
12641                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12642                         {
12643                                 // render surface with reflection texture as input
12644                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12645                                 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));
12646                                 RSurf_DrawBatch();
12647                         }
12648                 }
12649                 return;
12650         }
12651
12652         // render surface batch normally
12653         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12654         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12655         RSurf_DrawBatch();
12656 }
12657
12658 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12659 {
12660         // OpenGL 1.3 path - anything not completely ancient
12661         qboolean applycolor;
12662         qboolean applyfog;
12663         int layerindex;
12664         const texturelayer_t *layer;
12665         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);
12666         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12667
12668         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12669         {
12670                 vec4_t layercolor;
12671                 int layertexrgbscale;
12672                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12673                 {
12674                         if (layerindex == 0)
12675                                 GL_AlphaTest(true);
12676                         else
12677                         {
12678                                 GL_AlphaTest(false);
12679                                 GL_DepthFunc(GL_EQUAL);
12680                         }
12681                 }
12682                 GL_DepthMask(layer->depthmask && writedepth);
12683                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12684                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12685                 {
12686                         layertexrgbscale = 4;
12687                         VectorScale(layer->color, 0.25f, layercolor);
12688                 }
12689                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12690                 {
12691                         layertexrgbscale = 2;
12692                         VectorScale(layer->color, 0.5f, layercolor);
12693                 }
12694                 else
12695                 {
12696                         layertexrgbscale = 1;
12697                         VectorScale(layer->color, 1.0f, layercolor);
12698                 }
12699                 layercolor[3] = layer->color[3];
12700                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12701                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12702                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12703                 switch (layer->type)
12704                 {
12705                 case TEXTURELAYERTYPE_LITTEXTURE:
12706                         // single-pass lightmapped texture with 2x rgbscale
12707                         R_Mesh_TexBind(0, r_texture_white);
12708                         R_Mesh_TexMatrix(0, NULL);
12709                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12710                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12711                         R_Mesh_TexBind(1, layer->texture);
12712                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12713                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12714                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12715                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12716                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12717                         else if (FAKELIGHT_ENABLED)
12718                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12719                         else if (rsurface.uselightmaptexture)
12720                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12721                         else
12722                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12723                         break;
12724                 case TEXTURELAYERTYPE_TEXTURE:
12725                         // singletexture unlit texture with transparency support
12726                         R_Mesh_TexBind(0, layer->texture);
12727                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12728                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12729                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12730                         R_Mesh_TexBind(1, 0);
12731                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12732                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12733                         break;
12734                 case TEXTURELAYERTYPE_FOG:
12735                         // singletexture fogging
12736                         if (layer->texture)
12737                         {
12738                                 R_Mesh_TexBind(0, layer->texture);
12739                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12740                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12741                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12742                         }
12743                         else
12744                         {
12745                                 R_Mesh_TexBind(0, 0);
12746                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12747                         }
12748                         R_Mesh_TexBind(1, 0);
12749                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12750                         // generate a color array for the fog pass
12751                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12752                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12753                         RSurf_DrawBatch();
12754                         break;
12755                 default:
12756                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12757                 }
12758         }
12759         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12760         {
12761                 GL_DepthFunc(GL_LEQUAL);
12762                 GL_AlphaTest(false);
12763         }
12764 }
12765
12766 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12767 {
12768         // OpenGL 1.1 - crusty old voodoo path
12769         qboolean applyfog;
12770         int layerindex;
12771         const texturelayer_t *layer;
12772         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);
12773         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12774
12775         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12776         {
12777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12778                 {
12779                         if (layerindex == 0)
12780                                 GL_AlphaTest(true);
12781                         else
12782                         {
12783                                 GL_AlphaTest(false);
12784                                 GL_DepthFunc(GL_EQUAL);
12785                         }
12786                 }
12787                 GL_DepthMask(layer->depthmask && writedepth);
12788                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12789                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12790                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12791                 switch (layer->type)
12792                 {
12793                 case TEXTURELAYERTYPE_LITTEXTURE:
12794                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12795                         {
12796                                 // two-pass lit texture with 2x rgbscale
12797                                 // first the lightmap pass
12798                                 R_Mesh_TexBind(0, r_texture_white);
12799                                 R_Mesh_TexMatrix(0, NULL);
12800                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12801                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12802                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12803                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12804                                 else if (FAKELIGHT_ENABLED)
12805                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12806                                 else if (rsurface.uselightmaptexture)
12807                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12808                                 else
12809                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12810                                 // then apply the texture to it
12811                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12812                                 R_Mesh_TexBind(0, layer->texture);
12813                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12814                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12815                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12816                                 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);
12817                         }
12818                         else
12819                         {
12820                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12821                                 R_Mesh_TexBind(0, layer->texture);
12822                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12823                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12824                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12825                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12826                                         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);
12827                                 else
12828                                         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);
12829                         }
12830                         break;
12831                 case TEXTURELAYERTYPE_TEXTURE:
12832                         // singletexture unlit texture with transparency support
12833                         R_Mesh_TexBind(0, layer->texture);
12834                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12835                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12836                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12837                         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);
12838                         break;
12839                 case TEXTURELAYERTYPE_FOG:
12840                         // singletexture fogging
12841                         if (layer->texture)
12842                         {
12843                                 R_Mesh_TexBind(0, layer->texture);
12844                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12845                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12846                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12847                         }
12848                         else
12849                         {
12850                                 R_Mesh_TexBind(0, 0);
12851                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12852                         }
12853                         // generate a color array for the fog pass
12854                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12855                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12856                         RSurf_DrawBatch();
12857                         break;
12858                 default:
12859                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12860                 }
12861         }
12862         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12863         {
12864                 GL_DepthFunc(GL_LEQUAL);
12865                 GL_AlphaTest(false);
12866         }
12867 }
12868
12869 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12870 {
12871         int vi;
12872         int j;
12873         r_vertexgeneric_t *batchvertex;
12874         float c[4];
12875
12876         GL_AlphaTest(false);
12877 //      R_Mesh_ResetTextureState();
12878         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12879
12880         if(rsurface.texture && rsurface.texture->currentskinframe)
12881         {
12882                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12883                 c[3] *= rsurface.texture->currentalpha;
12884         }
12885         else
12886         {
12887                 c[0] = 1;
12888                 c[1] = 0;
12889                 c[2] = 1;
12890                 c[3] = 1;
12891         }
12892
12893         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12894         {
12895                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12896                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12897                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12898         }
12899
12900         // brighten it up (as texture value 127 means "unlit")
12901         c[0] *= 2 * r_refdef.view.colorscale;
12902         c[1] *= 2 * r_refdef.view.colorscale;
12903         c[2] *= 2 * r_refdef.view.colorscale;
12904
12905         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12906                 c[3] *= r_wateralpha.value;
12907
12908         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12909         {
12910                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12911                 GL_DepthMask(false);
12912         }
12913         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12914         {
12915                 GL_BlendFunc(GL_ONE, GL_ONE);
12916                 GL_DepthMask(false);
12917         }
12918         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12919         {
12920                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12921                 GL_DepthMask(false);
12922         }
12923         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12924         {
12925                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12926                 GL_DepthMask(false);
12927         }
12928         else
12929         {
12930                 GL_BlendFunc(GL_ONE, GL_ZERO);
12931                 GL_DepthMask(writedepth);
12932         }
12933
12934         if (r_showsurfaces.integer == 3)
12935         {
12936                 rsurface.passcolor4f = NULL;
12937
12938                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12939                 {
12940                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12941
12942                         rsurface.passcolor4f = NULL;
12943                         rsurface.passcolor4f_vertexbuffer = 0;
12944                         rsurface.passcolor4f_bufferoffset = 0;
12945                 }
12946                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12947                 {
12948                         qboolean applycolor = true;
12949                         float one = 1.0;
12950
12951                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12952
12953                         r_refdef.lightmapintensity = 1;
12954                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12955                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12956                 }
12957                 else if (FAKELIGHT_ENABLED)
12958                 {
12959                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12960
12961                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12962                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12963                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12964                 }
12965                 else
12966                 {
12967                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12968
12969                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12970                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12971                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12972                 }
12973
12974                 if(!rsurface.passcolor4f)
12975                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12976
12977                 RSurf_DrawBatch_GL11_ApplyAmbient();
12978                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12979                 if(r_refdef.fogenabled)
12980                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12981                 RSurf_DrawBatch_GL11_ClampColor();
12982
12983                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12984                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12985                 RSurf_DrawBatch();
12986         }
12987         else if (!r_refdef.view.showdebug)
12988         {
12989                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12990                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12991                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12992                 {
12993                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12994                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12995                 }
12996                 R_Mesh_PrepareVertices_Generic_Unlock();
12997                 RSurf_DrawBatch();
12998         }
12999         else if (r_showsurfaces.integer == 4)
13000         {
13001                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13002                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13003                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13004                 {
13005                         unsigned char c = vi << 3;
13006                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13007                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13008                 }
13009                 R_Mesh_PrepareVertices_Generic_Unlock();
13010                 RSurf_DrawBatch();
13011         }
13012         else if (r_showsurfaces.integer == 2)
13013         {
13014                 const int *e;
13015                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13016                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13017                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13018                 {
13019                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13020                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13021                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13022                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13023                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13024                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13025                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13026                 }
13027                 R_Mesh_PrepareVertices_Generic_Unlock();
13028                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13029         }
13030         else
13031         {
13032                 int texturesurfaceindex;
13033                 int k;
13034                 const msurface_t *surface;
13035                 unsigned char surfacecolor4ub[4];
13036                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13037                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13038                 vi = 0;
13039                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13040                 {
13041                         surface = texturesurfacelist[texturesurfaceindex];
13042                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13043                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13044                         for (j = 0;j < surface->num_vertices;j++)
13045                         {
13046                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13047                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13048                                 vi++;
13049                         }
13050                 }
13051                 R_Mesh_PrepareVertices_Generic_Unlock();
13052                 RSurf_DrawBatch();
13053         }
13054 }
13055
13056 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13057 {
13058         CHECKGLERROR
13059         RSurf_SetupDepthAndCulling();
13060         if (r_showsurfaces.integer)
13061         {
13062                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13063                 return;
13064         }
13065         switch (vid.renderpath)
13066         {
13067         case RENDERPATH_GL20:
13068         case RENDERPATH_CGGL:
13069         case RENDERPATH_D3D9:
13070         case RENDERPATH_D3D10:
13071         case RENDERPATH_D3D11:
13072                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13073                 break;
13074         case RENDERPATH_GL13:
13075                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13076                 break;
13077         case RENDERPATH_GL11:
13078                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13079                 break;
13080         }
13081         CHECKGLERROR
13082 }
13083
13084 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13085 {
13086         CHECKGLERROR
13087         RSurf_SetupDepthAndCulling();
13088         if (r_showsurfaces.integer)
13089         {
13090                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13091                 return;
13092         }
13093         switch (vid.renderpath)
13094         {
13095         case RENDERPATH_GL20:
13096         case RENDERPATH_CGGL:
13097         case RENDERPATH_D3D9:
13098         case RENDERPATH_D3D10:
13099         case RENDERPATH_D3D11:
13100                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13101                 break;
13102         case RENDERPATH_GL13:
13103                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13104                 break;
13105         case RENDERPATH_GL11:
13106                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13107                 break;
13108         }
13109         CHECKGLERROR
13110 }
13111
13112 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13113 {
13114         int i, j;
13115         int texturenumsurfaces, endsurface;
13116         texture_t *texture;
13117         const msurface_t *surface;
13118 #define MAXBATCH_TRANSPARENTSURFACES 256
13119         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13120
13121         // if the model is static it doesn't matter what value we give for
13122         // wantnormals and wanttangents, so this logic uses only rules applicable
13123         // to a model, knowing that they are meaningless otherwise
13124         if (ent == r_refdef.scene.worldentity)
13125                 RSurf_ActiveWorldEntity();
13126         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13127                 RSurf_ActiveModelEntity(ent, false, false, false);
13128         else
13129         {
13130                 switch (vid.renderpath)
13131                 {
13132                 case RENDERPATH_GL20:
13133                 case RENDERPATH_CGGL:
13134                 case RENDERPATH_D3D9:
13135                 case RENDERPATH_D3D10:
13136                 case RENDERPATH_D3D11:
13137                         RSurf_ActiveModelEntity(ent, true, true, false);
13138                         break;
13139                 case RENDERPATH_GL13:
13140                 case RENDERPATH_GL11:
13141                         RSurf_ActiveModelEntity(ent, true, false, false);
13142                         break;
13143                 }
13144         }
13145
13146         if (r_transparentdepthmasking.integer)
13147         {
13148                 qboolean setup = false;
13149                 for (i = 0;i < numsurfaces;i = j)
13150                 {
13151                         j = i + 1;
13152                         surface = rsurface.modelsurfaces + surfacelist[i];
13153                         texture = surface->texture;
13154                         rsurface.texture = R_GetCurrentTexture(texture);
13155                         rsurface.lightmaptexture = NULL;
13156                         rsurface.deluxemaptexture = NULL;
13157                         rsurface.uselightmaptexture = false;
13158                         // scan ahead until we find a different texture
13159                         endsurface = min(i + 1024, numsurfaces);
13160                         texturenumsurfaces = 0;
13161                         texturesurfacelist[texturenumsurfaces++] = surface;
13162                         for (;j < endsurface;j++)
13163                         {
13164                                 surface = rsurface.modelsurfaces + surfacelist[j];
13165                                 if (texture != surface->texture)
13166                                         break;
13167                                 texturesurfacelist[texturenumsurfaces++] = surface;
13168                         }
13169                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13170                                 continue;
13171                         // render the range of surfaces as depth
13172                         if (!setup)
13173                         {
13174                                 setup = true;
13175                                 GL_ColorMask(0,0,0,0);
13176                                 GL_Color(1,1,1,1);
13177                                 GL_DepthTest(true);
13178                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13179                                 GL_DepthMask(true);
13180                                 GL_AlphaTest(false);
13181 //                              R_Mesh_ResetTextureState();
13182                                 R_SetupShader_DepthOrShadow();
13183                         }
13184                         RSurf_SetupDepthAndCulling();
13185                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13186                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13187                         RSurf_DrawBatch();
13188                 }
13189                 if (setup)
13190                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13191         }
13192
13193         for (i = 0;i < numsurfaces;i = j)
13194         {
13195                 j = i + 1;
13196                 surface = rsurface.modelsurfaces + surfacelist[i];
13197                 texture = surface->texture;
13198                 rsurface.texture = R_GetCurrentTexture(texture);
13199                 // scan ahead until we find a different texture
13200                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13201                 texturenumsurfaces = 0;
13202                 texturesurfacelist[texturenumsurfaces++] = surface;
13203                 if(FAKELIGHT_ENABLED)
13204                 {
13205                         rsurface.lightmaptexture = NULL;
13206                         rsurface.deluxemaptexture = NULL;
13207                         rsurface.uselightmaptexture = false;
13208                         for (;j < endsurface;j++)
13209                         {
13210                                 surface = rsurface.modelsurfaces + surfacelist[j];
13211                                 if (texture != surface->texture)
13212                                         break;
13213                                 texturesurfacelist[texturenumsurfaces++] = surface;
13214                         }
13215                 }
13216                 else
13217                 {
13218                         rsurface.lightmaptexture = surface->lightmaptexture;
13219                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13220                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13221                         for (;j < endsurface;j++)
13222                         {
13223                                 surface = rsurface.modelsurfaces + surfacelist[j];
13224                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13225                                         break;
13226                                 texturesurfacelist[texturenumsurfaces++] = surface;
13227                         }
13228                 }
13229                 // render the range of surfaces
13230                 if (ent == r_refdef.scene.worldentity)
13231                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13232                 else
13233                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13234         }
13235         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13236         GL_AlphaTest(false);
13237 }
13238
13239 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13240 {
13241         // transparent surfaces get pushed off into the transparent queue
13242         int surfacelistindex;
13243         const msurface_t *surface;
13244         vec3_t tempcenter, center;
13245         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13246         {
13247                 surface = texturesurfacelist[surfacelistindex];
13248                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13249                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13250                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13251                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13252                 if (queueentity->transparent_offset) // transparent offset
13253                 {
13254                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13255                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13256                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13257                 }
13258                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13259         }
13260 }
13261
13262 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13263 {
13264         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13265                 return;
13266         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13267                 return;
13268         RSurf_SetupDepthAndCulling();
13269         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13270         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13271         RSurf_DrawBatch();
13272 }
13273
13274 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13275 {
13276         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13277         CHECKGLERROR
13278         if (depthonly)
13279                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13280         else if (prepass)
13281         {
13282                 if (!rsurface.texture->currentnumlayers)
13283                         return;
13284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13285                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13286                 else
13287                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13288         }
13289         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13290                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13291         else if (!rsurface.texture->currentnumlayers)
13292                 return;
13293         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13294         {
13295                 // in the deferred case, transparent surfaces were queued during prepass
13296                 if (!r_shadow_usingdeferredprepass)
13297                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13298         }
13299         else
13300         {
13301                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13302                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13303         }
13304         CHECKGLERROR
13305 }
13306
13307 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13308 {
13309         int i, j;
13310         texture_t *texture;
13311         // break the surface list down into batches by texture and use of lightmapping
13312         for (i = 0;i < numsurfaces;i = j)
13313         {
13314                 j = i + 1;
13315                 // texture is the base texture pointer, rsurface.texture is the
13316                 // current frame/skin the texture is directing us to use (for example
13317                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13318                 // use skin 1 instead)
13319                 texture = surfacelist[i]->texture;
13320                 rsurface.texture = R_GetCurrentTexture(texture);
13321                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13322                 {
13323                         // if this texture is not the kind we want, skip ahead to the next one
13324                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13325                                 ;
13326                         continue;
13327                 }
13328                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13329                 {
13330                         rsurface.lightmaptexture = NULL;
13331                         rsurface.deluxemaptexture = NULL;
13332                         rsurface.uselightmaptexture = false;
13333                         // simply scan ahead until we find a different texture or lightmap state
13334                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13335                                 ;
13336                 }
13337                 else
13338                 {
13339                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13340                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13341                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13342                         // simply scan ahead until we find a different texture or lightmap state
13343                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13344                                 ;
13345                 }
13346                 // render the range of surfaces
13347                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13348         }
13349 }
13350
13351 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13352 {
13353         CHECKGLERROR
13354         if (depthonly)
13355                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13356         else if (prepass)
13357         {
13358                 if (!rsurface.texture->currentnumlayers)
13359                         return;
13360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13361                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13362                 else
13363                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13364         }
13365         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13366                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13367         else if (!rsurface.texture->currentnumlayers)
13368                 return;
13369         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13370         {
13371                 // in the deferred case, transparent surfaces were queued during prepass
13372                 if (!r_shadow_usingdeferredprepass)
13373                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13374         }
13375         else
13376         {
13377                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13378                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13379         }
13380         CHECKGLERROR
13381 }
13382
13383 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13384 {
13385         int i, j;
13386         texture_t *texture;
13387         // break the surface list down into batches by texture and use of lightmapping
13388         for (i = 0;i < numsurfaces;i = j)
13389         {
13390                 j = i + 1;
13391                 // texture is the base texture pointer, rsurface.texture is the
13392                 // current frame/skin the texture is directing us to use (for example
13393                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13394                 // use skin 1 instead)
13395                 texture = surfacelist[i]->texture;
13396                 rsurface.texture = R_GetCurrentTexture(texture);
13397                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13398                 {
13399                         // if this texture is not the kind we want, skip ahead to the next one
13400                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13401                                 ;
13402                         continue;
13403                 }
13404                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13405                 {
13406                         rsurface.lightmaptexture = NULL;
13407                         rsurface.deluxemaptexture = NULL;
13408                         rsurface.uselightmaptexture = false;
13409                         // simply scan ahead until we find a different texture or lightmap state
13410                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13411                                 ;
13412                 }
13413                 else
13414                 {
13415                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13416                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13417                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13418                         // simply scan ahead until we find a different texture or lightmap state
13419                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13420                                 ;
13421                 }
13422                 // render the range of surfaces
13423                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13424         }
13425 }
13426
13427 float locboxvertex3f[6*4*3] =
13428 {
13429         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13430         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13431         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13432         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13433         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13434         1,0,0, 0,0,0, 0,1,0, 1,1,0
13435 };
13436
13437 unsigned short locboxelements[6*2*3] =
13438 {
13439          0, 1, 2, 0, 2, 3,
13440          4, 5, 6, 4, 6, 7,
13441          8, 9,10, 8,10,11,
13442         12,13,14, 12,14,15,
13443         16,17,18, 16,18,19,
13444         20,21,22, 20,22,23
13445 };
13446
13447 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13448 {
13449         int i, j;
13450         cl_locnode_t *loc = (cl_locnode_t *)ent;
13451         vec3_t mins, size;
13452         float vertex3f[6*4*3];
13453         CHECKGLERROR
13454         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13455         GL_DepthMask(false);
13456         GL_DepthRange(0, 1);
13457         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13458         GL_DepthTest(true);
13459         GL_CullFace(GL_NONE);
13460         R_EntityMatrix(&identitymatrix);
13461
13462 //      R_Mesh_ResetTextureState();
13463
13464         i = surfacelist[0];
13465         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13466                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13467                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13468                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13469
13470         if (VectorCompare(loc->mins, loc->maxs))
13471         {
13472                 VectorSet(size, 2, 2, 2);
13473                 VectorMA(loc->mins, -0.5f, size, mins);
13474         }
13475         else
13476         {
13477                 VectorCopy(loc->mins, mins);
13478                 VectorSubtract(loc->maxs, loc->mins, size);
13479         }
13480
13481         for (i = 0;i < 6*4*3;)
13482                 for (j = 0;j < 3;j++, i++)
13483                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13484
13485         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13486         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13487         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13488 }
13489
13490 void R_DrawLocs(void)
13491 {
13492         int index;
13493         cl_locnode_t *loc, *nearestloc;
13494         vec3_t center;
13495         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13496         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13497         {
13498                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13499                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13500         }
13501 }
13502
13503 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13504 {
13505         if (decalsystem->decals)
13506                 Mem_Free(decalsystem->decals);
13507         memset(decalsystem, 0, sizeof(*decalsystem));
13508 }
13509
13510 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)
13511 {
13512         tridecal_t *decal;
13513         tridecal_t *decals;
13514         int i;
13515
13516         // expand or initialize the system
13517         if (decalsystem->maxdecals <= decalsystem->numdecals)
13518         {
13519                 decalsystem_t old = *decalsystem;
13520                 qboolean useshortelements;
13521                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13522                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13523                 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)));
13524                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13525                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13526                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13527                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13528                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13529                 if (decalsystem->numdecals)
13530                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13531                 if (old.decals)
13532                         Mem_Free(old.decals);
13533                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13534                         decalsystem->element3i[i] = i;
13535                 if (useshortelements)
13536                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13537                                 decalsystem->element3s[i] = i;
13538         }
13539
13540         // grab a decal and search for another free slot for the next one
13541         decals = decalsystem->decals;
13542         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13543         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13544                 ;
13545         decalsystem->freedecal = i;
13546         if (decalsystem->numdecals <= i)
13547                 decalsystem->numdecals = i + 1;
13548
13549         // initialize the decal
13550         decal->lived = 0;
13551         decal->triangleindex = triangleindex;
13552         decal->surfaceindex = surfaceindex;
13553         decal->decalsequence = decalsequence;
13554         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13555         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13556         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13557         decal->color4ub[0][3] = 255;
13558         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13559         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13560         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13561         decal->color4ub[1][3] = 255;
13562         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13563         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13564         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13565         decal->color4ub[2][3] = 255;
13566         decal->vertex3f[0][0] = v0[0];
13567         decal->vertex3f[0][1] = v0[1];
13568         decal->vertex3f[0][2] = v0[2];
13569         decal->vertex3f[1][0] = v1[0];
13570         decal->vertex3f[1][1] = v1[1];
13571         decal->vertex3f[1][2] = v1[2];
13572         decal->vertex3f[2][0] = v2[0];
13573         decal->vertex3f[2][1] = v2[1];
13574         decal->vertex3f[2][2] = v2[2];
13575         decal->texcoord2f[0][0] = t0[0];
13576         decal->texcoord2f[0][1] = t0[1];
13577         decal->texcoord2f[1][0] = t1[0];
13578         decal->texcoord2f[1][1] = t1[1];
13579         decal->texcoord2f[2][0] = t2[0];
13580         decal->texcoord2f[2][1] = t2[1];
13581 }
13582
13583 extern cvar_t cl_decals_bias;
13584 extern cvar_t cl_decals_models;
13585 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13586 // baseparms, parms, temps
13587 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)
13588 {
13589         int cornerindex;
13590         int index;
13591         float v[9][3];
13592         const float *vertex3f;
13593         int numpoints;
13594         float points[2][9][3];
13595         float temp[3];
13596         float tc[9][2];
13597         float f;
13598         float c[9][4];
13599         const int *e;
13600
13601         e = rsurface.modelelement3i + 3*triangleindex;
13602
13603         vertex3f = rsurface.modelvertex3f;
13604
13605         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13606         {
13607                 index = 3*e[cornerindex];
13608                 VectorCopy(vertex3f + index, v[cornerindex]);
13609         }
13610         // cull backfaces
13611         //TriangleNormal(v[0], v[1], v[2], normal);
13612         //if (DotProduct(normal, localnormal) < 0.0f)
13613         //      continue;
13614         // clip by each of the box planes formed from the projection matrix
13615         // if anything survives, we emit the decal
13616         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]);
13617         if (numpoints < 3)
13618                 return;
13619         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]);
13620         if (numpoints < 3)
13621                 return;
13622         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]);
13623         if (numpoints < 3)
13624                 return;
13625         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]);
13626         if (numpoints < 3)
13627                 return;
13628         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]);
13629         if (numpoints < 3)
13630                 return;
13631         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]);
13632         if (numpoints < 3)
13633                 return;
13634         // some part of the triangle survived, so we have to accept it...
13635         if (dynamic)
13636         {
13637                 // dynamic always uses the original triangle
13638                 numpoints = 3;
13639                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13640                 {
13641                         index = 3*e[cornerindex];
13642                         VectorCopy(vertex3f + index, v[cornerindex]);
13643                 }
13644         }
13645         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13646         {
13647                 // convert vertex positions to texcoords
13648                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13649                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13650                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13651                 // calculate distance fade from the projection origin
13652                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13653                 f = bound(0.0f, f, 1.0f);
13654                 c[cornerindex][0] = r * f;
13655                 c[cornerindex][1] = g * f;
13656                 c[cornerindex][2] = b * f;
13657                 c[cornerindex][3] = 1.0f;
13658                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13659         }
13660         if (dynamic)
13661                 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);
13662         else
13663                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13664                         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);
13665 }
13666 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)
13667 {
13668         matrix4x4_t projection;
13669         decalsystem_t *decalsystem;
13670         qboolean dynamic;
13671         dp_model_t *model;
13672         const msurface_t *surface;
13673         const msurface_t *surfaces;
13674         const int *surfacelist;
13675         const texture_t *texture;
13676         int numtriangles;
13677         int numsurfacelist;
13678         int surfacelistindex;
13679         int surfaceindex;
13680         int triangleindex;
13681         float localorigin[3];
13682         float localnormal[3];
13683         float localmins[3];
13684         float localmaxs[3];
13685         float localsize;
13686         //float normal[3];
13687         float planes[6][4];
13688         float angles[3];
13689         bih_t *bih;
13690         int bih_triangles_count;
13691         int bih_triangles[256];
13692         int bih_surfaces[256];
13693
13694         decalsystem = &ent->decalsystem;
13695         model = ent->model;
13696         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13697         {
13698                 R_DecalSystem_Reset(&ent->decalsystem);
13699                 return;
13700         }
13701
13702         if (!model->brush.data_leafs && !cl_decals_models.integer)
13703         {
13704                 if (decalsystem->model)
13705                         R_DecalSystem_Reset(decalsystem);
13706                 return;
13707         }
13708
13709         if (decalsystem->model != model)
13710                 R_DecalSystem_Reset(decalsystem);
13711         decalsystem->model = model;
13712
13713         RSurf_ActiveModelEntity(ent, false, false, false);
13714
13715         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13716         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13717         VectorNormalize(localnormal);
13718         localsize = worldsize*rsurface.inversematrixscale;
13719         localmins[0] = localorigin[0] - localsize;
13720         localmins[1] = localorigin[1] - localsize;
13721         localmins[2] = localorigin[2] - localsize;
13722         localmaxs[0] = localorigin[0] + localsize;
13723         localmaxs[1] = localorigin[1] + localsize;
13724         localmaxs[2] = localorigin[2] + localsize;
13725
13726         //VectorCopy(localnormal, planes[4]);
13727         //VectorVectors(planes[4], planes[2], planes[0]);
13728         AnglesFromVectors(angles, localnormal, NULL, false);
13729         AngleVectors(angles, planes[0], planes[2], planes[4]);
13730         VectorNegate(planes[0], planes[1]);
13731         VectorNegate(planes[2], planes[3]);
13732         VectorNegate(planes[4], planes[5]);
13733         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13734         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13735         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13736         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13737         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13738         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13739
13740 #if 1
13741 // works
13742 {
13743         matrix4x4_t forwardprojection;
13744         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13745         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13746 }
13747 #else
13748 // broken
13749 {
13750         float projectionvector[4][3];
13751         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13752         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13753         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13754         projectionvector[0][0] = planes[0][0] * ilocalsize;
13755         projectionvector[0][1] = planes[1][0] * ilocalsize;
13756         projectionvector[0][2] = planes[2][0] * ilocalsize;
13757         projectionvector[1][0] = planes[0][1] * ilocalsize;
13758         projectionvector[1][1] = planes[1][1] * ilocalsize;
13759         projectionvector[1][2] = planes[2][1] * ilocalsize;
13760         projectionvector[2][0] = planes[0][2] * ilocalsize;
13761         projectionvector[2][1] = planes[1][2] * ilocalsize;
13762         projectionvector[2][2] = planes[2][2] * ilocalsize;
13763         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13764         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13765         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13766         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13767 }
13768 #endif
13769
13770         dynamic = model->surfmesh.isanimated;
13771         numsurfacelist = model->nummodelsurfaces;
13772         surfacelist = model->sortedmodelsurfaces;
13773         surfaces = model->data_surfaces;
13774
13775         bih = NULL;
13776         bih_triangles_count = -1;
13777         if(!dynamic)
13778         {
13779                 if(model->render_bih.numleafs)
13780                         bih = &model->render_bih;
13781                 else if(model->collision_bih.numleafs)
13782                         bih = &model->collision_bih;
13783         }
13784         if(bih)
13785                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13786         if(bih_triangles_count == 0)
13787                 return;
13788         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13789                 return;
13790         if(bih_triangles_count > 0)
13791         {
13792                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13793                 {
13794                         surfaceindex = bih_surfaces[triangleindex];
13795                         surface = surfaces + surfaceindex;
13796                         texture = surface->texture;
13797                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13798                                 continue;
13799                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13800                                 continue;
13801                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13802                 }
13803         }
13804         else
13805         {
13806                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13807                 {
13808                         surfaceindex = surfacelist[surfacelistindex];
13809                         surface = surfaces + surfaceindex;
13810                         // check cull box first because it rejects more than any other check
13811                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13812                                 continue;
13813                         // skip transparent surfaces
13814                         texture = surface->texture;
13815                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13816                                 continue;
13817                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13818                                 continue;
13819                         numtriangles = surface->num_triangles;
13820                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13821                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13822                 }
13823         }
13824 }
13825
13826 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13827 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)
13828 {
13829         int renderentityindex;
13830         float worldmins[3];
13831         float worldmaxs[3];
13832         entity_render_t *ent;
13833
13834         if (!cl_decals_newsystem.integer)
13835                 return;
13836
13837         worldmins[0] = worldorigin[0] - worldsize;
13838         worldmins[1] = worldorigin[1] - worldsize;
13839         worldmins[2] = worldorigin[2] - worldsize;
13840         worldmaxs[0] = worldorigin[0] + worldsize;
13841         worldmaxs[1] = worldorigin[1] + worldsize;
13842         worldmaxs[2] = worldorigin[2] + worldsize;
13843
13844         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13845
13846         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13847         {
13848                 ent = r_refdef.scene.entities[renderentityindex];
13849                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13850                         continue;
13851
13852                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13853         }
13854 }
13855
13856 typedef struct r_decalsystem_splatqueue_s
13857 {
13858         vec3_t worldorigin;
13859         vec3_t worldnormal;
13860         float color[4];
13861         float tcrange[4];
13862         float worldsize;
13863         int decalsequence;
13864 }
13865 r_decalsystem_splatqueue_t;
13866
13867 int r_decalsystem_numqueued = 0;
13868 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13869
13870 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)
13871 {
13872         r_decalsystem_splatqueue_t *queue;
13873
13874         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13875                 return;
13876
13877         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13878         VectorCopy(worldorigin, queue->worldorigin);
13879         VectorCopy(worldnormal, queue->worldnormal);
13880         Vector4Set(queue->color, r, g, b, a);
13881         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13882         queue->worldsize = worldsize;
13883         queue->decalsequence = cl.decalsequence++;
13884 }
13885
13886 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13887 {
13888         int i;
13889         r_decalsystem_splatqueue_t *queue;
13890
13891         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13892                 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);
13893         r_decalsystem_numqueued = 0;
13894 }
13895
13896 extern cvar_t cl_decals_max;
13897 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13898 {
13899         int i;
13900         decalsystem_t *decalsystem = &ent->decalsystem;
13901         int numdecals;
13902         int killsequence;
13903         tridecal_t *decal;
13904         float frametime;
13905         float lifetime;
13906
13907         if (!decalsystem->numdecals)
13908                 return;
13909
13910         if (r_showsurfaces.integer)
13911                 return;
13912
13913         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13914         {
13915                 R_DecalSystem_Reset(decalsystem);
13916                 return;
13917         }
13918
13919         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13920         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13921
13922         if (decalsystem->lastupdatetime)
13923                 frametime = (cl.time - decalsystem->lastupdatetime);
13924         else
13925                 frametime = 0;
13926         decalsystem->lastupdatetime = cl.time;
13927         decal = decalsystem->decals;
13928         numdecals = decalsystem->numdecals;
13929
13930         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13931         {
13932                 if (decal->color4ub[0][3])
13933                 {
13934                         decal->lived += frametime;
13935                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13936                         {
13937                                 memset(decal, 0, sizeof(*decal));
13938                                 if (decalsystem->freedecal > i)
13939                                         decalsystem->freedecal = i;
13940                         }
13941                 }
13942         }
13943         decal = decalsystem->decals;
13944         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13945                 numdecals--;
13946
13947         // collapse the array by shuffling the tail decals into the gaps
13948         for (;;)
13949         {
13950                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13951                         decalsystem->freedecal++;
13952                 if (decalsystem->freedecal == numdecals)
13953                         break;
13954                 decal[decalsystem->freedecal] = decal[--numdecals];
13955         }
13956
13957         decalsystem->numdecals = numdecals;
13958
13959         if (numdecals <= 0)
13960         {
13961                 // if there are no decals left, reset decalsystem
13962                 R_DecalSystem_Reset(decalsystem);
13963         }
13964 }
13965
13966 extern skinframe_t *decalskinframe;
13967 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13968 {
13969         int i;
13970         decalsystem_t *decalsystem = &ent->decalsystem;
13971         int numdecals;
13972         tridecal_t *decal;
13973         float faderate;
13974         float alpha;
13975         float *v3f;
13976         float *c4f;
13977         float *t2f;
13978         const int *e;
13979         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13980         int numtris = 0;
13981
13982         numdecals = decalsystem->numdecals;
13983         if (!numdecals)
13984                 return;
13985
13986         if (r_showsurfaces.integer)
13987                 return;
13988
13989         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13990         {
13991                 R_DecalSystem_Reset(decalsystem);
13992                 return;
13993         }
13994
13995         // if the model is static it doesn't matter what value we give for
13996         // wantnormals and wanttangents, so this logic uses only rules applicable
13997         // to a model, knowing that they are meaningless otherwise
13998         if (ent == r_refdef.scene.worldentity)
13999                 RSurf_ActiveWorldEntity();
14000         else
14001                 RSurf_ActiveModelEntity(ent, false, false, false);
14002
14003         decalsystem->lastupdatetime = cl.time;
14004         decal = decalsystem->decals;
14005
14006         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14007
14008         // update vertex positions for animated models
14009         v3f = decalsystem->vertex3f;
14010         c4f = decalsystem->color4f;
14011         t2f = decalsystem->texcoord2f;
14012         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14013         {
14014                 if (!decal->color4ub[0][3])
14015                         continue;
14016
14017                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14018                         continue;
14019
14020                 // update color values for fading decals
14021                 if (decal->lived >= cl_decals_time.value)
14022                 {
14023                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14024                         alpha *= (1.0f/255.0f);
14025                 }
14026                 else
14027                         alpha = 1.0f/255.0f;
14028
14029                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14030                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14031                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14032                 c4f[ 3] = 1;
14033                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14034                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14035                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14036                 c4f[ 7] = 1;
14037                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14038                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14039                 c4f[10] = decal->color4ub[2][2] * alpha;
14040                 c4f[11] = 1;
14041
14042                 t2f[0] = decal->texcoord2f[0][0];
14043                 t2f[1] = decal->texcoord2f[0][1];
14044                 t2f[2] = decal->texcoord2f[1][0];
14045                 t2f[3] = decal->texcoord2f[1][1];
14046                 t2f[4] = decal->texcoord2f[2][0];
14047                 t2f[5] = decal->texcoord2f[2][1];
14048
14049                 // update vertex positions for animated models
14050                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14051                 {
14052                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14053                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14054                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14055                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14056                 }
14057                 else
14058                 {
14059                         VectorCopy(decal->vertex3f[0], v3f);
14060                         VectorCopy(decal->vertex3f[1], v3f + 3);
14061                         VectorCopy(decal->vertex3f[2], v3f + 6);
14062                 }
14063
14064                 if (r_refdef.fogenabled)
14065                 {
14066                         alpha = RSurf_FogVertex(v3f);
14067                         VectorScale(c4f, alpha, c4f);
14068                         alpha = RSurf_FogVertex(v3f + 3);
14069                         VectorScale(c4f + 4, alpha, c4f + 4);
14070                         alpha = RSurf_FogVertex(v3f + 6);
14071                         VectorScale(c4f + 8, alpha, c4f + 8);
14072                 }
14073
14074                 v3f += 9;
14075                 c4f += 12;
14076                 t2f += 6;
14077                 numtris++;
14078         }
14079
14080         if (numtris > 0)
14081         {
14082                 r_refdef.stats.drawndecals += numtris;
14083
14084                 // now render the decals all at once
14085                 // (this assumes they all use one particle font texture!)
14086                 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);
14087 //              R_Mesh_ResetTextureState();
14088                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14089                 GL_DepthMask(false);
14090                 GL_DepthRange(0, 1);
14091                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14092                 GL_DepthTest(true);
14093                 GL_CullFace(GL_NONE);
14094                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14095                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14096                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14097         }
14098 }
14099
14100 static void R_DrawModelDecals(void)
14101 {
14102         int i, numdecals;
14103
14104         // fade faster when there are too many decals
14105         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14106         for (i = 0;i < r_refdef.scene.numentities;i++)
14107                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14108
14109         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14110         for (i = 0;i < r_refdef.scene.numentities;i++)
14111                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14112                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14113
14114         R_DecalSystem_ApplySplatEntitiesQueue();
14115
14116         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14117         for (i = 0;i < r_refdef.scene.numentities;i++)
14118                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14119
14120         r_refdef.stats.totaldecals += numdecals;
14121
14122         if (r_showsurfaces.integer)
14123                 return;
14124
14125         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14126
14127         for (i = 0;i < r_refdef.scene.numentities;i++)
14128         {
14129                 if (!r_refdef.viewcache.entityvisible[i])
14130                         continue;
14131                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14132                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14133         }
14134 }
14135
14136 extern cvar_t mod_collision_bih;
14137 void R_DrawDebugModel(void)
14138 {
14139         entity_render_t *ent = rsurface.entity;
14140         int i, j, k, l, flagsmask;
14141         const msurface_t *surface;
14142         dp_model_t *model = ent->model;
14143         vec3_t v;
14144
14145         switch(vid.renderpath)
14146         {
14147         case RENDERPATH_GL11:
14148         case RENDERPATH_GL13:
14149         case RENDERPATH_GL20:
14150         case RENDERPATH_CGGL:
14151                 break;
14152         case RENDERPATH_D3D9:
14153                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14154                 return;
14155         case RENDERPATH_D3D10:
14156                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14157                 return;
14158         case RENDERPATH_D3D11:
14159                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14160                 return;
14161         }
14162
14163         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14164
14165 //      R_Mesh_ResetTextureState();
14166         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14167         GL_DepthRange(0, 1);
14168         GL_DepthTest(!r_showdisabledepthtest.integer);
14169         GL_DepthMask(false);
14170         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14171
14172         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14173         {
14174                 int triangleindex;
14175                 int bihleafindex;
14176                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14177                 const q3mbrush_t *brush;
14178                 const bih_t *bih = &model->collision_bih;
14179                 const bih_leaf_t *bihleaf;
14180                 float vertex3f[3][3];
14181                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14182                 cullbox = false;
14183                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14184                 {
14185                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14186                                 continue;
14187                         switch (bihleaf->type)
14188                         {
14189                         case BIH_BRUSH:
14190                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14191                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14192                                 {
14193                                         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);
14194                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14195                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14196                                 }
14197                                 break;
14198                         case BIH_COLLISIONTRIANGLE:
14199                                 triangleindex = bihleaf->itemindex;
14200                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14201                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14202                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14203                                 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);
14204                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14205                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14206                                 break;
14207                         case BIH_RENDERTRIANGLE:
14208                                 triangleindex = bihleaf->itemindex;
14209                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14210                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14211                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14212                                 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);
14213                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14214                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14215                                 break;
14216                         }
14217                 }
14218         }
14219
14220         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14221
14222         if (r_showtris.integer || r_shownormals.integer)
14223         {
14224                 if (r_showdisabledepthtest.integer)
14225                 {
14226                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14227                         GL_DepthMask(false);
14228                 }
14229                 else
14230                 {
14231                         GL_BlendFunc(GL_ONE, GL_ZERO);
14232                         GL_DepthMask(true);
14233                 }
14234                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14235                 {
14236                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14237                                 continue;
14238                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14239                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14240                         {
14241                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14242                                 if (r_showtris.value > 0)
14243                                 {
14244                                         if (!rsurface.texture->currentlayers->depthmask)
14245                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14246                                         else if (ent == r_refdef.scene.worldentity)
14247                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14248                                         else
14249                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14250                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14251                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14252                                         RSurf_DrawBatch();
14253                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14254                                         CHECKGLERROR
14255                                 }
14256                                 if (r_shownormals.value < 0)
14257                                 {
14258                                         qglBegin(GL_LINES);
14259                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14260                                         {
14261                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14262                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14263                                                 qglVertex3f(v[0], v[1], v[2]);
14264                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14265                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14266                                                 qglVertex3f(v[0], v[1], v[2]);
14267                                         }
14268                                         qglEnd();
14269                                         CHECKGLERROR
14270                                 }
14271                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14272                                 {
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(r_refdef.view.colorscale, 0, 0, 1);
14278                                                 qglVertex3f(v[0], v[1], v[2]);
14279                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + 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                                         qglBegin(GL_LINES);
14286                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14287                                         {
14288                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14289                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14290                                                 qglVertex3f(v[0], v[1], v[2]);
14291                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14292                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14293                                                 qglVertex3f(v[0], v[1], v[2]);
14294                                         }
14295                                         qglEnd();
14296                                         CHECKGLERROR
14297                                         qglBegin(GL_LINES);
14298                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14299                                         {
14300                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14301                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14302                                                 qglVertex3f(v[0], v[1], v[2]);
14303                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14304                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14305                                                 qglVertex3f(v[0], v[1], v[2]);
14306                                         }
14307                                         qglEnd();
14308                                         CHECKGLERROR
14309                                 }
14310                         }
14311                 }
14312                 rsurface.texture = NULL;
14313         }
14314 }
14315
14316 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14317 int r_maxsurfacelist = 0;
14318 const msurface_t **r_surfacelist = NULL;
14319 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14320 {
14321         int i, j, endj, flagsmask;
14322         dp_model_t *model = r_refdef.scene.worldmodel;
14323         msurface_t *surfaces;
14324         unsigned char *update;
14325         int numsurfacelist = 0;
14326         if (model == NULL)
14327                 return;
14328
14329         if (r_maxsurfacelist < model->num_surfaces)
14330         {
14331                 r_maxsurfacelist = model->num_surfaces;
14332                 if (r_surfacelist)
14333                         Mem_Free((msurface_t**)r_surfacelist);
14334                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14335         }
14336
14337         RSurf_ActiveWorldEntity();
14338
14339         surfaces = model->data_surfaces;
14340         update = model->brushq1.lightmapupdateflags;
14341
14342         // update light styles on this submodel
14343         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14344         {
14345                 model_brush_lightstyleinfo_t *style;
14346                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14347                 {
14348                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14349                         {
14350                                 int *list = style->surfacelist;
14351                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14352                                 for (j = 0;j < style->numsurfaces;j++)
14353                                         update[list[j]] = true;
14354                         }
14355                 }
14356         }
14357
14358         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14359
14360         if (debug)
14361         {
14362                 R_DrawDebugModel();
14363                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14364                 return;
14365         }
14366
14367         rsurface.lightmaptexture = NULL;
14368         rsurface.deluxemaptexture = NULL;
14369         rsurface.uselightmaptexture = false;
14370         rsurface.texture = NULL;
14371         rsurface.rtlight = NULL;
14372         numsurfacelist = 0;
14373         // add visible surfaces to draw list
14374         for (i = 0;i < model->nummodelsurfaces;i++)
14375         {
14376                 j = model->sortedmodelsurfaces[i];
14377                 if (r_refdef.viewcache.world_surfacevisible[j])
14378                         r_surfacelist[numsurfacelist++] = surfaces + j;
14379         }
14380         // update lightmaps if needed
14381         if (model->brushq1.firstrender)
14382         {
14383                 model->brushq1.firstrender = false;
14384                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14385                         if (update[j])
14386                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14387         }
14388         else if (update)
14389         {
14390                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14391                         if (r_refdef.viewcache.world_surfacevisible[j])
14392                                 if (update[j])
14393                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14394         }
14395         // don't do anything if there were no surfaces
14396         if (!numsurfacelist)
14397         {
14398                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14399                 return;
14400         }
14401         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14402         GL_AlphaTest(false);
14403
14404         // add to stats if desired
14405         if (r_speeds.integer && !skysurfaces && !depthonly)
14406         {
14407                 r_refdef.stats.world_surfaces += numsurfacelist;
14408                 for (j = 0;j < numsurfacelist;j++)
14409                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14410         }
14411
14412         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14413 }
14414
14415 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14416 {
14417         int i, j, endj, flagsmask;
14418         dp_model_t *model = ent->model;
14419         msurface_t *surfaces;
14420         unsigned char *update;
14421         int numsurfacelist = 0;
14422         if (model == NULL)
14423                 return;
14424
14425         if (r_maxsurfacelist < model->num_surfaces)
14426         {
14427                 r_maxsurfacelist = model->num_surfaces;
14428                 if (r_surfacelist)
14429                         Mem_Free((msurface_t **)r_surfacelist);
14430                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14431         }
14432
14433         // if the model is static it doesn't matter what value we give for
14434         // wantnormals and wanttangents, so this logic uses only rules applicable
14435         // to a model, knowing that they are meaningless otherwise
14436         if (ent == r_refdef.scene.worldentity)
14437                 RSurf_ActiveWorldEntity();
14438         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14439                 RSurf_ActiveModelEntity(ent, false, false, false);
14440         else if (prepass)
14441                 RSurf_ActiveModelEntity(ent, true, true, true);
14442         else if (depthonly)
14443         {
14444                 switch (vid.renderpath)
14445                 {
14446                 case RENDERPATH_GL20:
14447                 case RENDERPATH_CGGL:
14448                 case RENDERPATH_D3D9:
14449                 case RENDERPATH_D3D10:
14450                 case RENDERPATH_D3D11:
14451                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14452                         break;
14453                 case RENDERPATH_GL13:
14454                 case RENDERPATH_GL11:
14455                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14456                         break;
14457                 }
14458         }
14459         else
14460         {
14461                 switch (vid.renderpath)
14462                 {
14463                 case RENDERPATH_GL20:
14464                 case RENDERPATH_CGGL:
14465                 case RENDERPATH_D3D9:
14466                 case RENDERPATH_D3D10:
14467                 case RENDERPATH_D3D11:
14468                         RSurf_ActiveModelEntity(ent, true, true, false);
14469                         break;
14470                 case RENDERPATH_GL13:
14471                 case RENDERPATH_GL11:
14472                         RSurf_ActiveModelEntity(ent, true, false, false);
14473                         break;
14474                 }
14475         }
14476
14477         surfaces = model->data_surfaces;
14478         update = model->brushq1.lightmapupdateflags;
14479
14480         // update light styles
14481         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14482         {
14483                 model_brush_lightstyleinfo_t *style;
14484                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14485                 {
14486                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14487                         {
14488                                 int *list = style->surfacelist;
14489                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14490                                 for (j = 0;j < style->numsurfaces;j++)
14491                                         update[list[j]] = true;
14492                         }
14493                 }
14494         }
14495
14496         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14497
14498         if (debug)
14499         {
14500                 R_DrawDebugModel();
14501                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14502                 return;
14503         }
14504
14505         rsurface.lightmaptexture = NULL;
14506         rsurface.deluxemaptexture = NULL;
14507         rsurface.uselightmaptexture = false;
14508         rsurface.texture = NULL;
14509         rsurface.rtlight = NULL;
14510         numsurfacelist = 0;
14511         // add visible surfaces to draw list
14512         for (i = 0;i < model->nummodelsurfaces;i++)
14513                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14514         // don't do anything if there were no surfaces
14515         if (!numsurfacelist)
14516         {
14517                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14518                 return;
14519         }
14520         // update lightmaps if needed
14521         if (update)
14522         {
14523                 int updated = 0;
14524                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14525                 {
14526                         if (update[j])
14527                         {
14528                                 updated++;
14529                                 R_BuildLightMap(ent, surfaces + j);
14530                         }
14531                 }
14532         }
14533         if (update)
14534                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14535                         if (update[j])
14536                                 R_BuildLightMap(ent, surfaces + j);
14537         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14538         GL_AlphaTest(false);
14539
14540         // add to stats if desired
14541         if (r_speeds.integer && !skysurfaces && !depthonly)
14542         {
14543                 r_refdef.stats.entities_surfaces += numsurfacelist;
14544                 for (j = 0;j < numsurfacelist;j++)
14545                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14546         }
14547
14548         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14549 }
14550
14551 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14552 {
14553         static texture_t texture;
14554         static msurface_t surface;
14555         const msurface_t *surfacelist = &surface;
14556
14557         // fake enough texture and surface state to render this geometry
14558
14559         texture.update_lastrenderframe = -1; // regenerate this texture
14560         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14561         texture.currentskinframe = skinframe;
14562         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14563         texture.offsetmapping = OFFSETMAPPING_OFF;
14564         texture.offsetscale = 1;
14565         texture.specularscalemod = 1;
14566         texture.specularpowermod = 1;
14567
14568         surface.texture = &texture;
14569         surface.num_triangles = numtriangles;
14570         surface.num_firsttriangle = firsttriangle;
14571         surface.num_vertices = numvertices;
14572         surface.num_firstvertex = firstvertex;
14573
14574         // now render it
14575         rsurface.texture = R_GetCurrentTexture(surface.texture);
14576         rsurface.lightmaptexture = NULL;
14577         rsurface.deluxemaptexture = NULL;
14578         rsurface.uselightmaptexture = false;
14579         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14580 }
14581
14582 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)
14583 {
14584         static msurface_t surface;
14585         const msurface_t *surfacelist = &surface;
14586
14587         // fake enough texture and surface state to render this geometry
14588         surface.texture = texture;
14589         surface.num_triangles = numtriangles;
14590         surface.num_firsttriangle = firsttriangle;
14591         surface.num_vertices = numvertices;
14592         surface.num_firstvertex = firstvertex;
14593
14594         // now render it
14595         rsurface.texture = R_GetCurrentTexture(surface.texture);
14596         rsurface.lightmaptexture = NULL;
14597         rsurface.deluxemaptexture = NULL;
14598         rsurface.uselightmaptexture = false;
14599         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14600 }