]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
offsetmapping: make it work on ATI Radeon 9500-9800/X300 again
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151
152 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)"};
153 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
154 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"};
155 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
156 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
157 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
158
159 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
160 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
161 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
162 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
163
164 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
165 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
166 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
167 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
168 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
169 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
170 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
171
172 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
173 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
174 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
175 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)"};
176
177 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"};
178
179 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"};
180
181 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
182
183 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 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)"};
190
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
192 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"};
193
194 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)"};
195
196 extern cvar_t v_glslgamma;
197
198 extern qboolean v_flipped_state;
199
200 static struct r_bloomstate_s
201 {
202         qboolean enabled;
203         qboolean hdr;
204
205         int bloomwidth, bloomheight;
206
207         int screentexturewidth, screentextureheight;
208         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
209
210         int bloomtexturewidth, bloomtextureheight;
211         rtexture_t *texture_bloom;
212
213         // arrays for rendering the screen passes
214         float screentexcoord2f[8];
215         float bloomtexcoord2f[8];
216         float offsettexcoord2f[8];
217
218         r_viewport_t viewport;
219 }
220 r_bloomstate;
221
222 r_waterstate_t r_waterstate;
223
224 /// shadow volume bsp struct with automatically growing nodes buffer
225 svbsp_t r_svbsp;
226
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
240
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
243 {
244         char basename[64];
245         rtexture_t *texture;
246 }
247 cubemapinfo_t;
248
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
251
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
255
256 typedef struct r_qwskincache_s
257 {
258         char name[MAX_QPATH];
259         skinframe_t *skinframe;
260 }
261 r_qwskincache_t;
262
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
265
266 /// vertex coordinates for a quad that covers the screen exactly
267 extern const float r_screenvertex3f[12];
268 extern const float r_d3dscreenvertex3f[12];
269 const float r_screenvertex3f[12] =
270 {
271         0, 0, 0,
272         1, 0, 0,
273         1, 1, 0,
274         0, 1, 0
275 };
276 const float r_d3dscreenvertex3f[12] =
277 {
278         0, 1, 0,
279         1, 1, 0,
280         1, 0, 0,
281         0, 0, 0
282 };
283
284 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
285 {
286         int i;
287         for (i = 0;i < verts;i++)
288         {
289                 out[0] = in[0] * r;
290                 out[1] = in[1] * g;
291                 out[2] = in[2] * b;
292                 out[3] = in[3];
293                 in += 4;
294                 out += 4;
295         }
296 }
297
298 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = r;
304                 out[1] = g;
305                 out[2] = b;
306                 out[3] = a;
307                 out += 4;
308         }
309 }
310
311 // FIXME: move this to client?
312 void FOG_clear(void)
313 {
314         if (gamemode == GAME_NEHAHRA)
315         {
316                 Cvar_Set("gl_fogenable", "0");
317                 Cvar_Set("gl_fogdensity", "0.2");
318                 Cvar_Set("gl_fogred", "0.3");
319                 Cvar_Set("gl_foggreen", "0.3");
320                 Cvar_Set("gl_fogblue", "0.3");
321         }
322         r_refdef.fog_density = 0;
323         r_refdef.fog_red = 0;
324         r_refdef.fog_green = 0;
325         r_refdef.fog_blue = 0;
326         r_refdef.fog_alpha = 1;
327         r_refdef.fog_start = 0;
328         r_refdef.fog_end = 16384;
329         r_refdef.fog_height = 1<<30;
330         r_refdef.fog_fadedepth = 128;
331         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
332 }
333
334 static void R_BuildBlankTextures(void)
335 {
336         unsigned char data[4];
337         data[2] = 128; // normal X
338         data[1] = 128; // normal Y
339         data[0] = 255; // normal Z
340         data[3] = 128; // height
341         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
342         data[0] = 255;
343         data[1] = 255;
344         data[2] = 255;
345         data[3] = 255;
346         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
347         data[0] = 128;
348         data[1] = 128;
349         data[2] = 128;
350         data[3] = 255;
351         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352         data[0] = 0;
353         data[1] = 0;
354         data[2] = 0;
355         data[3] = 255;
356         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357 }
358
359 static void R_BuildNoTexture(void)
360 {
361         int x, y;
362         unsigned char pix[16][16][4];
363         // this makes a light grey/dark grey checkerboard texture
364         for (y = 0;y < 16;y++)
365         {
366                 for (x = 0;x < 16;x++)
367                 {
368                         if ((y < 8) ^ (x < 8))
369                         {
370                                 pix[y][x][0] = 128;
371                                 pix[y][x][1] = 128;
372                                 pix[y][x][2] = 128;
373                                 pix[y][x][3] = 255;
374                         }
375                         else
376                         {
377                                 pix[y][x][0] = 64;
378                                 pix[y][x][1] = 64;
379                                 pix[y][x][2] = 64;
380                                 pix[y][x][3] = 255;
381                         }
382                 }
383         }
384         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildWhiteCube(void)
388 {
389         unsigned char data[6*1*1*4];
390         memset(data, 255, sizeof(data));
391         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNormalizationCube(void)
395 {
396         int x, y, side;
397         vec3_t v;
398         vec_t s, t, intensity;
399 #define NORMSIZE 64
400         unsigned char *data;
401         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
402         for (side = 0;side < 6;side++)
403         {
404                 for (y = 0;y < NORMSIZE;y++)
405                 {
406                         for (x = 0;x < NORMSIZE;x++)
407                         {
408                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
409                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
410                                 switch(side)
411                                 {
412                                 default:
413                                 case 0:
414                                         v[0] = 1;
415                                         v[1] = -t;
416                                         v[2] = -s;
417                                         break;
418                                 case 1:
419                                         v[0] = -1;
420                                         v[1] = -t;
421                                         v[2] = s;
422                                         break;
423                                 case 2:
424                                         v[0] = s;
425                                         v[1] = 1;
426                                         v[2] = t;
427                                         break;
428                                 case 3:
429                                         v[0] = s;
430                                         v[1] = -1;
431                                         v[2] = -t;
432                                         break;
433                                 case 4:
434                                         v[0] = s;
435                                         v[1] = -t;
436                                         v[2] = 1;
437                                         break;
438                                 case 5:
439                                         v[0] = -s;
440                                         v[1] = -t;
441                                         v[2] = -1;
442                                         break;
443                                 }
444                                 intensity = 127.0f / sqrt(DotProduct(v, v));
445                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
446                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
447                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
448                                 data[((side*64+y)*64+x)*4+3] = 255;
449                         }
450                 }
451         }
452         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
453         Mem_Free(data);
454 }
455
456 static void R_BuildFogTexture(void)
457 {
458         int x, b;
459 #define FOGWIDTH 256
460         unsigned char data1[FOGWIDTH][4];
461         //unsigned char data2[FOGWIDTH][4];
462         double d, r, alpha;
463
464         r_refdef.fogmasktable_start = r_refdef.fog_start;
465         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
466         r_refdef.fogmasktable_range = r_refdef.fogrange;
467         r_refdef.fogmasktable_density = r_refdef.fog_density;
468
469         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
470         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
471         {
472                 d = (x * r - r_refdef.fogmasktable_start);
473                 if(developer_extra.integer)
474                         Con_DPrintf("%f ", d);
475                 d = max(0, d);
476                 if (r_fog_exp2.integer)
477                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
478                 else
479                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
480                 if(developer_extra.integer)
481                         Con_DPrintf(" : %f ", alpha);
482                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
483                 if(developer_extra.integer)
484                         Con_DPrintf(" = %f\n", alpha);
485                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
486         }
487
488         for (x = 0;x < FOGWIDTH;x++)
489         {
490                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
491                 data1[x][0] = b;
492                 data1[x][1] = b;
493                 data1[x][2] = b;
494                 data1[x][3] = 255;
495                 //data2[x][0] = 255 - b;
496                 //data2[x][1] = 255 - b;
497                 //data2[x][2] = 255 - b;
498                 //data2[x][3] = 255;
499         }
500         if (r_texture_fogattenuation)
501         {
502                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
503                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
504         }
505         else
506         {
507                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
509         }
510 }
511
512 static void R_BuildFogHeightTexture(void)
513 {
514         unsigned char *inpixels;
515         int size;
516         int x;
517         int y;
518         int j;
519         float c[4];
520         float f;
521         inpixels = NULL;
522         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
523         if (r_refdef.fogheighttexturename[0])
524                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
525         if (!inpixels)
526         {
527                 r_refdef.fog_height_tablesize = 0;
528                 if (r_texture_fogheighttexture)
529                         R_FreeTexture(r_texture_fogheighttexture);
530                 r_texture_fogheighttexture = NULL;
531                 if (r_refdef.fog_height_table2d)
532                         Mem_Free(r_refdef.fog_height_table2d);
533                 r_refdef.fog_height_table2d = NULL;
534                 if (r_refdef.fog_height_table1d)
535                         Mem_Free(r_refdef.fog_height_table1d);
536                 r_refdef.fog_height_table1d = NULL;
537                 return;
538         }
539         size = image_width;
540         r_refdef.fog_height_tablesize = size;
541         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
542         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
543         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
544         Mem_Free(inpixels);
545         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
546         // average fog color table accounting for every fog layer between a point
547         // and the camera.  (Note: attenuation is handled separately!)
548         for (y = 0;y < size;y++)
549         {
550                 for (x = 0;x < size;x++)
551                 {
552                         Vector4Clear(c);
553                         f = 0;
554                         if (x < y)
555                         {
556                                 for (j = x;j <= y;j++)
557                                 {
558                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
559                                         f++;
560                                 }
561                         }
562                         else
563                         {
564                                 for (j = x;j >= y;j--)
565                                 {
566                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
567                                         f++;
568                                 }
569                         }
570                         f = 1.0f / f;
571                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
572                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
573                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
574                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
575                 }
576         }
577         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
578 }
579
580 //=======================================================================================================================================================
581
582 static const char *builtinshaderstring =
583 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
584 "// written by Forest 'LordHavoc' Hale\n"
585 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
586 "\n"
587 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
588 "# define USEFOG\n"
589 "#endif\n"
590 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
591 "#define USELIGHTMAP\n"
592 "#endif\n"
593 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
594 "#define USEEYEVECTOR\n"
595 "#endif\n"
596 "\n"
597 "#ifdef USESHADOWMAP2D\n"
598 "# ifdef GL_EXT_gpu_shader4\n"
599 "#   extension GL_EXT_gpu_shader4 : enable\n"
600 "# endif\n"
601 "# ifdef GL_ARB_texture_gather\n"
602 "#   extension GL_ARB_texture_gather : enable\n"
603 "# else\n"
604 "#   ifdef GL_AMD_texture_texture4\n"
605 "#     extension GL_AMD_texture_texture4 : enable\n"
606 "#   endif\n"
607 "# endif\n"
608 "#endif\n"
609 "\n"
610 "//#ifdef USESHADOWSAMPLER\n"
611 "//# extension GL_ARB_shadow : enable\n"
612 "//#endif\n"
613 "\n"
614 "//#ifdef __GLSL_CG_DATA_TYPES\n"
615 "//# define myhalf half\n"
616 "//# define myhalf2 half2\n"
617 "//# define myhalf3 half3\n"
618 "//# define myhalf4 half4\n"
619 "//#else\n"
620 "# define myhalf float\n"
621 "# define myhalf2 vec2\n"
622 "# define myhalf3 vec3\n"
623 "# define myhalf4 vec4\n"
624 "//#endif\n"
625 "\n"
626 "#ifdef VERTEX_SHADER\n"
627 "uniform mat4 ModelViewProjectionMatrix;\n"
628 "#endif\n"
629 "\n"
630 "#ifdef MODE_DEPTH_OR_SHADOW\n"
631 "#ifdef VERTEX_SHADER\n"
632 "void main(void)\n"
633 "{\n"
634 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
635 "}\n"
636 "#endif\n"
637 "#else // !MODE_DEPTH_ORSHADOW\n"
638 "\n"
639 "\n"
640 "\n"
641 "\n"
642 "#ifdef MODE_SHOWDEPTH\n"
643 "#ifdef VERTEX_SHADER\n"
644 "void main(void)\n"
645 "{\n"
646 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
647 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_FragColor = gl_Color;\n"
655 "}\n"
656 "#endif\n"
657 "#else // !MODE_SHOWDEPTH\n"
658 "\n"
659 "\n"
660 "\n"
661 "\n"
662 "#ifdef MODE_POSTPROCESS\n"
663 "varying vec2 TexCoord1;\n"
664 "varying vec2 TexCoord2;\n"
665 "\n"
666 "#ifdef VERTEX_SHADER\n"
667 "void main(void)\n"
668 "{\n"
669 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
670 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
671 "#ifdef USEBLOOM\n"
672 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
673 "#endif\n"
674 "}\n"
675 "#endif\n"
676 "\n"
677 "#ifdef FRAGMENT_SHADER\n"
678 "uniform sampler2D Texture_First;\n"
679 "#ifdef USEBLOOM\n"
680 "uniform sampler2D Texture_Second;\n"
681 "uniform vec4 BloomColorSubtract;\n"
682 "#endif\n"
683 "#ifdef USEGAMMARAMPS\n"
684 "uniform sampler2D Texture_GammaRamps;\n"
685 "#endif\n"
686 "#ifdef USESATURATION\n"
687 "uniform float Saturation;\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "uniform vec4 ViewTintColor;\n"
691 "#endif\n"
692 "//uncomment these if you want to use them:\n"
693 "uniform vec4 UserVec1;\n"
694 "uniform vec4 UserVec2;\n"
695 "// uniform vec4 UserVec3;\n"
696 "// uniform vec4 UserVec4;\n"
697 "// uniform float ClientTime;\n"
698 "uniform vec2 PixelSize;\n"
699 "void main(void)\n"
700 "{\n"
701 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
702 "#ifdef USEBLOOM\n"
703 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
704 "#endif\n"
705 "#ifdef USEVIEWTINT\n"
706 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
707 "#endif\n"
708 "\n"
709 "#ifdef USEPOSTPROCESSING\n"
710 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
711 "// 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"
712 "       float sobel = 1.0;\n"
713 "       // vec2 ts = textureSize(Texture_First, 0);\n"
714 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
715 "       vec2 px = PixelSize;\n"
716 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
717 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
718 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
721 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
724 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
727 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
728 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
729 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
730 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
731 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
732 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
733 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
734 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
735 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
736 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
737 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
738 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
739 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
740 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
741 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
746 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
747 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USESATURATION\n"
751 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
752 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
753 "       // 'vampire sight' effect, wheres red is compensated\n"
754 "       #ifdef SATURATION_REDCOMPENSATE\n"
755 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
756 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
757 "               gl_FragColor.r += rboost;\n"
758 "       #else\n"
759 "               // normal desaturation\n"
760 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
761 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
762 "       #endif\n"
763 "#endif\n"
764 "\n"
765 "#ifdef USEGAMMARAMPS\n"
766 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
767 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
768 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
769 "#endif\n"
770 "}\n"
771 "#endif\n"
772 "#else // !MODE_POSTPROCESS\n"
773 "\n"
774 "\n"
775 "\n"
776 "\n"
777 "#ifdef MODE_GENERIC\n"
778 "#ifdef USEDIFFUSE\n"
779 "varying vec2 TexCoord1;\n"
780 "#endif\n"
781 "#ifdef USESPECULAR\n"
782 "varying vec2 TexCoord2;\n"
783 "#endif\n"
784 "#ifdef VERTEX_SHADER\n"
785 "void main(void)\n"
786 "{\n"
787 "       gl_FrontColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
790 "#endif\n"
791 "#ifdef USESPECULAR\n"
792 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
793 "#endif\n"
794 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
795 "}\n"
796 "#endif\n"
797 "\n"
798 "#ifdef FRAGMENT_SHADER\n"
799 "#ifdef USEDIFFUSE\n"
800 "uniform sampler2D Texture_First;\n"
801 "#endif\n"
802 "#ifdef USESPECULAR\n"
803 "uniform sampler2D Texture_Second;\n"
804 "#endif\n"
805 "\n"
806 "void main(void)\n"
807 "{\n"
808 "       gl_FragColor = gl_Color;\n"
809 "#ifdef USEDIFFUSE\n"
810 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
811 "#endif\n"
812 "\n"
813 "#ifdef USESPECULAR\n"
814 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
815 "# ifdef USECOLORMAPPING\n"
816 "       gl_FragColor *= tex2;\n"
817 "# endif\n"
818 "# ifdef USEGLOW\n"
819 "       gl_FragColor += tex2;\n"
820 "# endif\n"
821 "# ifdef USEVERTEXTEXTUREBLEND\n"
822 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
823 "# endif\n"
824 "#endif\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_GENERIC\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "#ifdef MODE_BLOOMBLUR\n"
833 "varying TexCoord;\n"
834 "#ifdef VERTEX_SHADER\n"
835 "void main(void)\n"
836 "{\n"
837 "       gl_FrontColor = gl_Color;\n"
838 "       TexCoord = gl_MultiTexCoord0.xy;\n"
839 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
840 "}\n"
841 "#endif\n"
842 "\n"
843 "#ifdef FRAGMENT_SHADER\n"
844 "uniform sampler2D Texture_First;\n"
845 "uniform vec4 BloomBlur_Parameters;\n"
846 "\n"
847 "void main(void)\n"
848 "{\n"
849 "       int i;\n"
850 "       vec2 tc = TexCoord;\n"
851 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
852 "       tc += BloomBlur_Parameters.xy;\n"
853 "       for (i = 1;i < SAMPLES;i++)\n"
854 "       {\n"
855 "               color += texture2D(Texture_First, tc).rgb;\n"
856 "               tc += BloomBlur_Parameters.xy;\n"
857 "       }\n"
858 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
859 "}\n"
860 "#endif\n"
861 "#else // !MODE_BLOOMBLUR\n"
862 "#ifdef MODE_REFRACTION\n"
863 "varying vec2 TexCoord;\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "#ifdef VERTEX_SHADER\n"
867 "\n"
868 "void main(void)\n"
869 "{\n"
870 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
871 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
872 "       ModelViewProjectionPosition = gl_Position;\n"
873 "}\n"
874 "#endif\n"
875 "\n"
876 "#ifdef FRAGMENT_SHADER\n"
877 "uniform sampler2D Texture_Normal;\n"
878 "uniform sampler2D Texture_Refraction;\n"
879 "uniform sampler2D Texture_Reflection;\n"
880 "\n"
881 "uniform vec4 DistortScaleRefractReflect;\n"
882 "uniform vec4 ScreenScaleRefractReflect;\n"
883 "uniform vec4 ScreenCenterRefractReflect;\n"
884 "uniform vec4 RefractColor;\n"
885 "uniform vec4 ReflectColor;\n"
886 "uniform float ReflectFactor;\n"
887 "uniform float ReflectOffset;\n"
888 "\n"
889 "void main(void)\n"
890 "{\n"
891 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
892 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
893 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
894 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
895 "       // FIXME temporary hack to detect the case that the reflection\n"
896 "       // gets blackened at edges due to leaving the area that contains actual\n"
897 "       // content.\n"
898 "       // Remove this 'ack once we have a better way to stop this thing from\n"
899 "       // 'appening.\n"
900 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
901 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
902 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
903 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
904 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
905 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
906 "}\n"
907 "#endif\n"
908 "#else // !MODE_REFRACTION\n"
909 "\n"
910 "\n"
911 "\n"
912 "\n"
913 "#ifdef MODE_WATER\n"
914 "varying vec2 TexCoord;\n"
915 "varying vec3 EyeVector;\n"
916 "varying vec4 ModelViewProjectionPosition;\n"
917 "#ifdef VERTEX_SHADER\n"
918 "uniform vec3 EyePosition;\n"
919 "uniform mat4 TexMatrix;\n"
920 "\n"
921 "void main(void)\n"
922 "{\n"
923 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
924 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
925 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
926 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
927 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
928 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
929 "       ModelViewProjectionPosition = gl_Position;\n"
930 "}\n"
931 "#endif\n"
932 "\n"
933 "#ifdef FRAGMENT_SHADER\n"
934 "uniform sampler2D Texture_Normal;\n"
935 "uniform sampler2D Texture_Refraction;\n"
936 "uniform sampler2D Texture_Reflection;\n"
937 "\n"
938 "uniform vec4 DistortScaleRefractReflect;\n"
939 "uniform vec4 ScreenScaleRefractReflect;\n"
940 "uniform vec4 ScreenCenterRefractReflect;\n"
941 "uniform vec4 RefractColor;\n"
942 "uniform vec4 ReflectColor;\n"
943 "uniform float ReflectFactor;\n"
944 "uniform float ReflectOffset;\n"
945 "uniform float ClientTime;\n"
946 "#ifdef USENORMALMAPSCROLLBLEND\n"
947 "uniform vec2 NormalmapScrollBlend;\n"
948 "#endif\n"
949 "\n"
950 "void main(void)\n"
951 "{\n"
952 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
953 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
954 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
955 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
956 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
957 "       #ifdef USENORMALMAPSCROLLBLEND\n"
958 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
959 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
960 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
961 "       #else\n"
962 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
963 "       #endif\n"
964 "       // FIXME temporary hack to detect the case that the reflection\n"
965 "       // gets blackened at edges due to leaving the area that contains actual\n"
966 "       // content.\n"
967 "       // Remove this 'ack once we have a better way to stop this thing from\n"
968 "       // 'appening.\n"
969 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
970 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
971 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
972 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
973 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
974 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
975 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
976 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
977 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
978 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
979 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
980 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
981 "       gl_FragColor.a = f1 + 0.5;\n"
982 "}\n"
983 "#endif\n"
984 "#else // !MODE_WATER\n"
985 "\n"
986 "\n"
987 "\n"
988 "\n"
989 "// common definitions between vertex shader and fragment shader:\n"
990 "\n"
991 "varying vec2 TexCoord;\n"
992 "#ifdef USEVERTEXTEXTUREBLEND\n"
993 "varying vec2 TexCoord2;\n"
994 "#endif\n"
995 "#ifdef USELIGHTMAP\n"
996 "varying vec2 TexCoordLightmap;\n"
997 "#endif\n"
998 "\n"
999 "#ifdef MODE_LIGHTSOURCE\n"
1000 "varying vec3 CubeVector;\n"
1001 "#endif\n"
1002 "\n"
1003 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1004 "varying vec3 LightVector;\n"
1005 "#endif\n"
1006 "\n"
1007 "#ifdef USEEYEVECTOR\n"
1008 "varying vec3 EyeVector;\n"
1009 "#endif\n"
1010 "#ifdef USEFOG\n"
1011 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1012 "#endif\n"
1013 "\n"
1014 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1015 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1016 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1017 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1018 "#endif\n"
1019 "\n"
1020 "#ifdef USEREFLECTION\n"
1021 "varying vec4 ModelViewProjectionPosition;\n"
1022 "#endif\n"
1023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1024 "uniform vec3 LightPosition;\n"
1025 "varying vec4 ModelViewPosition;\n"
1026 "#endif\n"
1027 "\n"
1028 "#ifdef MODE_LIGHTSOURCE\n"
1029 "uniform vec3 LightPosition;\n"
1030 "#endif\n"
1031 "uniform vec3 EyePosition;\n"
1032 "#ifdef MODE_LIGHTDIRECTION\n"
1033 "uniform vec3 LightDir;\n"
1034 "#endif\n"
1035 "uniform vec4 FogPlane;\n"
1036 "\n"
1037 "#ifdef USESHADOWMAPORTHO\n"
1038 "varying vec3 ShadowMapTC;\n"
1039 "#endif\n"
1040 "\n"
1041 "\n"
1042 "\n"
1043 "\n"
1044 "\n"
1045 "// 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"
1046 "\n"
1047 "// fragment shader specific:\n"
1048 "#ifdef FRAGMENT_SHADER\n"
1049 "\n"
1050 "uniform sampler2D Texture_Normal;\n"
1051 "uniform sampler2D Texture_Color;\n"
1052 "uniform sampler2D Texture_Gloss;\n"
1053 "#ifdef USEGLOW\n"
1054 "uniform sampler2D Texture_Glow;\n"
1055 "#endif\n"
1056 "#ifdef USEVERTEXTEXTUREBLEND\n"
1057 "uniform sampler2D Texture_SecondaryNormal;\n"
1058 "uniform sampler2D Texture_SecondaryColor;\n"
1059 "uniform sampler2D Texture_SecondaryGloss;\n"
1060 "#ifdef USEGLOW\n"
1061 "uniform sampler2D Texture_SecondaryGlow;\n"
1062 "#endif\n"
1063 "#endif\n"
1064 "#ifdef USECOLORMAPPING\n"
1065 "uniform sampler2D Texture_Pants;\n"
1066 "uniform sampler2D Texture_Shirt;\n"
1067 "#endif\n"
1068 "#ifdef USEFOG\n"
1069 "#ifdef USEFOGHEIGHTTEXTURE\n"
1070 "uniform sampler2D Texture_FogHeightTexture;\n"
1071 "#endif\n"
1072 "uniform sampler2D Texture_FogMask;\n"
1073 "#endif\n"
1074 "#ifdef USELIGHTMAP\n"
1075 "uniform sampler2D Texture_Lightmap;\n"
1076 "#endif\n"
1077 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1078 "uniform sampler2D Texture_Deluxemap;\n"
1079 "#endif\n"
1080 "#ifdef USEREFLECTION\n"
1081 "uniform sampler2D Texture_Reflection;\n"
1082 "#endif\n"
1083 "\n"
1084 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1085 "uniform sampler2D Texture_ScreenDepth;\n"
1086 "uniform sampler2D Texture_ScreenNormalMap;\n"
1087 "#endif\n"
1088 "#ifdef USEDEFERREDLIGHTMAP\n"
1089 "uniform sampler2D Texture_ScreenDiffuse;\n"
1090 "uniform sampler2D Texture_ScreenSpecular;\n"
1091 "#endif\n"
1092 "\n"
1093 "uniform myhalf3 Color_Pants;\n"
1094 "uniform myhalf3 Color_Shirt;\n"
1095 "uniform myhalf3 FogColor;\n"
1096 "\n"
1097 "#ifdef USEFOG\n"
1098 "uniform float FogRangeRecip;\n"
1099 "uniform float FogPlaneViewDist;\n"
1100 "uniform float FogHeightFade;\n"
1101 "vec3 FogVertex(vec3 surfacecolor)\n"
1102 "{\n"
1103 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1104 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1105 "       float fogfrac;\n"
1106 "#ifdef USEFOGHEIGHTTEXTURE\n"
1107 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1108 "       fogfrac = fogheightpixel.a;\n"
1109 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1110 "#else\n"
1111 "# ifdef USEFOGOUTSIDE\n"
1112 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1113 "# else\n"
1114 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1115 "# endif\n"
1116 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1117 "#endif\n"
1118 "}\n"
1119 "#endif\n"
1120 "\n"
1121 "#ifdef USEOFFSETMAPPING\n"
1122 "uniform float OffsetMapping_Scale;\n"
1123 "vec2 OffsetMapping(vec2 TexCoord)\n"
1124 "{\n"
1125 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1126 "       // 14 sample relief mapping: linear search and then binary search\n"
1127 "       // this basically steps forward a small amount repeatedly until it finds\n"
1128 "       // itself inside solid, then jitters forward and back using decreasing\n"
1129 "       // amounts to find the impact\n"
1130 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1131 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1132 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1133 "       vec3 RT = vec3(TexCoord, 1);\n"
1134 "       OffsetVector *= 0.1;\n"
1135 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1138 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1139 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1145 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1146 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1147 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1148 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1149 "       return RT.xy;\n"
1150 "#else\n"
1151 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1152 "       // this basically moves forward the full distance, and then backs up based\n"
1153 "       // on height of samples\n"
1154 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1155 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1156 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1157 "       TexCoord += OffsetVector;\n"
1158 "       OffsetVector *= 0.5;\n"
1159 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1160 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1161 "       return TexCoord;\n"
1162 "#endif\n"
1163 "}\n"
1164 "#endif // USEOFFSETMAPPING\n"
1165 "\n"
1166 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1167 "uniform sampler2D Texture_Attenuation;\n"
1168 "uniform samplerCube Texture_Cube;\n"
1169 "#endif\n"
1170 "\n"
1171 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1172 "\n"
1173 "#ifdef USESHADOWMAP2D\n"
1174 "# ifdef USESHADOWSAMPLER\n"
1175 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1176 "# else\n"
1177 "uniform sampler2D Texture_ShadowMap2D;\n"
1178 "# endif\n"
1179 "#endif\n"
1180 "\n"
1181 "#ifdef USESHADOWMAPVSDCT\n"
1182 "uniform samplerCube Texture_CubeProjection;\n"
1183 "#endif\n"
1184 "\n"
1185 "#if defined(USESHADOWMAP2D)\n"
1186 "uniform vec2 ShadowMap_TextureScale;\n"
1187 "uniform vec4 ShadowMap_Parameters;\n"
1188 "#endif\n"
1189 "\n"
1190 "#if defined(USESHADOWMAP2D)\n"
1191 "# ifdef USESHADOWMAPORTHO\n"
1192 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1193 "# else\n"
1194 "#  ifdef USESHADOWMAPVSDCT\n"
1195 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1196 "{\n"
1197 "       vec3 adir = abs(dir);\n"
1198 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1199 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1200 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1201 "}\n"
1202 "#  else\n"
1203 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1204 "{\n"
1205 "       vec3 adir = abs(dir);\n"
1206 "       float ma = adir.z;\n"
1207 "       vec4 proj = vec4(dir, 2.5);\n"
1208 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1209 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1210 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1211 "       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"
1212 "}\n"
1213 "#  endif\n"
1214 "# endif\n"
1215 "#endif // defined(USESHADOWMAP2D)\n"
1216 "\n"
1217 "# ifdef USESHADOWMAP2D\n"
1218 "float ShadowMapCompare(vec3 dir)\n"
1219 "{\n"
1220 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1221 "       float f;\n"
1222 "\n"
1223 "#  ifdef USESHADOWSAMPLER\n"
1224 "#    ifdef USESHADOWMAPPCF\n"
1225 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1226 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1227 "       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"
1228 "#    else\n"
1229 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1230 "#    endif\n"
1231 "#  else\n"
1232 "#    ifdef USESHADOWMAPPCF\n"
1233 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1234 "#      ifdef GL_ARB_texture_gather\n"
1235 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1236 "#      else\n"
1237 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1238 "#      endif\n"
1239 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1242 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1243 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1244 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1245 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1246 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1247 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1248 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1249 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1250 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1251 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1252 "       locols.yz += group2.ab;\n"
1253 "       hicols.yz += group8.rg;\n"
1254 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1255 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1256 "                               mix(locols, hicols, offset.y);\n"
1257 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1258 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1259 "       f = dot(cols, vec4(1.0/25.0));\n"
1260 "#      else\n"
1261 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1262 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1263 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1264 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1265 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1266 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1267 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1268 "#      endif\n"
1269 "#     else\n"
1270 "#      ifdef GL_EXT_gpu_shader4\n"
1271 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1272 "#      else\n"
1273 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1274 "#      endif\n"
1275 "#      if USESHADOWMAPPCF > 1\n"
1276 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1277 "       center *= ShadowMap_TextureScale;\n"
1278 "       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"
1279 "       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"
1280 "       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"
1281 "       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"
1282 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1283 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1284 "#      else\n"
1285 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1286 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1287 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1288 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1289 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1290 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1291 "#      endif\n"
1292 "#     endif\n"
1293 "#    else\n"
1294 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1295 "#    endif\n"
1296 "#  endif\n"
1297 "#  ifdef USESHADOWMAPORTHO\n"
1298 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1299 "#  else\n"
1300 "       return f;\n"
1301 "#  endif\n"
1302 "}\n"
1303 "# endif\n"
1304 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1305 "#endif // FRAGMENT_SHADER\n"
1306 "\n"
1307 "\n"
1308 "\n"
1309 "\n"
1310 "#ifdef MODE_DEFERREDGEOMETRY\n"
1311 "#ifdef VERTEX_SHADER\n"
1312 "uniform mat4 TexMatrix;\n"
1313 "#ifdef USEVERTEXTEXTUREBLEND\n"
1314 "uniform mat4 BackgroundTexMatrix;\n"
1315 "#endif\n"
1316 "uniform mat4 ModelViewMatrix;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1320 "#ifdef USEVERTEXTEXTUREBLEND\n"
1321 "       gl_FrontColor = gl_Color;\n"
1322 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1323 "#endif\n"
1324 "\n"
1325 "       // transform unnormalized eye direction into tangent space\n"
1326 "#ifdef USEOFFSETMAPPING\n"
1327 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1328 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1329 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1330 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1331 "#endif\n"
1332 "\n"
1333 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1334 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1335 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1336 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1337 "}\n"
1338 "#endif // VERTEX_SHADER\n"
1339 "\n"
1340 "#ifdef FRAGMENT_SHADER\n"
1341 "void main(void)\n"
1342 "{\n"
1343 "#ifdef USEOFFSETMAPPING\n"
1344 "       // apply offsetmapping\n"
1345 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1346 "#define TexCoord TexCoordOffset\n"
1347 "#endif\n"
1348 "\n"
1349 "#ifdef USEALPHAKILL\n"
1350 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1351 "               discard;\n"
1352 "#endif\n"
1353 "\n"
1354 "#ifdef USEVERTEXTEXTUREBLEND\n"
1355 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1356 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1357 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1358 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1359 "#endif\n"
1360 "\n"
1361 "#ifdef USEVERTEXTEXTUREBLEND\n"
1362 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1363 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1364 "#else\n"
1365 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1366 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1367 "#endif\n"
1368 "\n"
1369 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1370 "}\n"
1371 "#endif // FRAGMENT_SHADER\n"
1372 "#else // !MODE_DEFERREDGEOMETRY\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "\n"
1377 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1378 "#ifdef VERTEX_SHADER\n"
1379 "uniform mat4 ModelViewMatrix;\n"
1380 "void main(void)\n"
1381 "{\n"
1382 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1383 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1384 "}\n"
1385 "#endif // VERTEX_SHADER\n"
1386 "\n"
1387 "#ifdef FRAGMENT_SHADER\n"
1388 "uniform mat4 ViewToLight;\n"
1389 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1390 "uniform vec2 ScreenToDepth;\n"
1391 "uniform myhalf3 DeferredColor_Ambient;\n"
1392 "uniform myhalf3 DeferredColor_Diffuse;\n"
1393 "#ifdef USESPECULAR\n"
1394 "uniform myhalf3 DeferredColor_Specular;\n"
1395 "uniform myhalf SpecularPower;\n"
1396 "#endif\n"
1397 "uniform myhalf2 PixelToScreenTexCoord;\n"
1398 "void main(void)\n"
1399 "{\n"
1400 "       // calculate viewspace pixel position\n"
1401 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1402 "       vec3 position;\n"
1403 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1404 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1405 "       // decode viewspace pixel normal\n"
1406 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1407 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1408 "       // surfacenormal = pixel normal in viewspace\n"
1409 "       // LightVector = pixel to light in viewspace\n"
1410 "       // CubeVector = position in lightspace\n"
1411 "       // eyevector = pixel to view in viewspace\n"
1412 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1413 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1414 "#ifdef USEDIFFUSE\n"
1415 "       // calculate diffuse shading\n"
1416 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1417 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1418 "#endif\n"
1419 "#ifdef USESPECULAR\n"
1420 "       // calculate directional shading\n"
1421 "       vec3 eyevector = position * -1.0;\n"
1422 "#  ifdef USEEXACTSPECULARMATH\n"
1423 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1424 "#  else\n"
1425 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1426 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1427 "#  endif\n"
1428 "#endif\n"
1429 "\n"
1430 "#if defined(USESHADOWMAP2D)\n"
1431 "       fade *= ShadowMapCompare(CubeVector);\n"
1432 "#endif\n"
1433 "\n"
1434 "#ifdef USEDIFFUSE\n"
1435 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1436 "#else\n"
1437 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1438 "#endif\n"
1439 "#ifdef USESPECULAR\n"
1440 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1441 "#else\n"
1442 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1443 "#endif\n"
1444 "\n"
1445 "# ifdef USECUBEFILTER\n"
1446 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1447 "       gl_FragData[0].rgb *= cubecolor;\n"
1448 "       gl_FragData[1].rgb *= cubecolor;\n"
1449 "# endif\n"
1450 "}\n"
1451 "#endif // FRAGMENT_SHADER\n"
1452 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1453 "\n"
1454 "\n"
1455 "\n"
1456 "\n"
1457 "#ifdef VERTEX_SHADER\n"
1458 "uniform mat4 TexMatrix;\n"
1459 "#ifdef USEVERTEXTEXTUREBLEND\n"
1460 "uniform mat4 BackgroundTexMatrix;\n"
1461 "#endif\n"
1462 "#ifdef MODE_LIGHTSOURCE\n"
1463 "uniform mat4 ModelToLight;\n"
1464 "#endif\n"
1465 "#ifdef USESHADOWMAPORTHO\n"
1466 "uniform mat4 ShadowMapMatrix;\n"
1467 "#endif\n"
1468 "void main(void)\n"
1469 "{\n"
1470 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1471 "       gl_FrontColor = gl_Color;\n"
1472 "#endif\n"
1473 "       // copy the surface texcoord\n"
1474 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1475 "#ifdef USEVERTEXTEXTUREBLEND\n"
1476 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1477 "#endif\n"
1478 "#ifdef USELIGHTMAP\n"
1479 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1480 "#endif\n"
1481 "\n"
1482 "#ifdef MODE_LIGHTSOURCE\n"
1483 "       // transform vertex position into light attenuation/cubemap space\n"
1484 "       // (-1 to +1 across the light box)\n"
1485 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1486 "\n"
1487 "# ifdef USEDIFFUSE\n"
1488 "       // transform unnormalized light direction into tangent space\n"
1489 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1490 "       //  normalize it per pixel)\n"
1491 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1492 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1493 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1494 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1495 "# endif\n"
1496 "#endif\n"
1497 "\n"
1498 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1499 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1500 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1501 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1502 "#endif\n"
1503 "\n"
1504 "       // transform unnormalized eye direction into tangent space\n"
1505 "#ifdef USEEYEVECTOR\n"
1506 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1507 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1508 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1509 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1510 "#endif\n"
1511 "\n"
1512 "#ifdef USEFOG\n"
1513 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1514 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1515 "#endif\n"
1516 "\n"
1517 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1518 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1519 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1520 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1521 "#endif\n"
1522 "\n"
1523 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1524 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1525 "\n"
1526 "#ifdef USESHADOWMAPORTHO\n"
1527 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1528 "#endif\n"
1529 "\n"
1530 "#ifdef USEREFLECTION\n"
1531 "       ModelViewProjectionPosition = gl_Position;\n"
1532 "#endif\n"
1533 "}\n"
1534 "#endif // VERTEX_SHADER\n"
1535 "\n"
1536 "\n"
1537 "\n"
1538 "\n"
1539 "#ifdef FRAGMENT_SHADER\n"
1540 "#ifdef USEDEFERREDLIGHTMAP\n"
1541 "uniform myhalf2 PixelToScreenTexCoord;\n"
1542 "uniform myhalf3 DeferredMod_Diffuse;\n"
1543 "uniform myhalf3 DeferredMod_Specular;\n"
1544 "#endif\n"
1545 "uniform myhalf3 Color_Ambient;\n"
1546 "uniform myhalf3 Color_Diffuse;\n"
1547 "uniform myhalf3 Color_Specular;\n"
1548 "uniform myhalf SpecularPower;\n"
1549 "#ifdef USEGLOW\n"
1550 "uniform myhalf3 Color_Glow;\n"
1551 "#endif\n"
1552 "uniform myhalf Alpha;\n"
1553 "#ifdef USEREFLECTION\n"
1554 "uniform vec4 DistortScaleRefractReflect;\n"
1555 "uniform vec4 ScreenScaleRefractReflect;\n"
1556 "uniform vec4 ScreenCenterRefractReflect;\n"
1557 "uniform myhalf4 ReflectColor;\n"
1558 "#endif\n"
1559 "#ifdef USEREFLECTCUBE\n"
1560 "uniform mat4 ModelToReflectCube;\n"
1561 "uniform sampler2D Texture_ReflectMask;\n"
1562 "uniform samplerCube Texture_ReflectCube;\n"
1563 "#endif\n"
1564 "#ifdef MODE_LIGHTDIRECTION\n"
1565 "uniform myhalf3 LightColor;\n"
1566 "#endif\n"
1567 "#ifdef MODE_LIGHTSOURCE\n"
1568 "uniform myhalf3 LightColor;\n"
1569 "#endif\n"
1570 "void main(void)\n"
1571 "{\n"
1572 "#ifdef USEOFFSETMAPPING\n"
1573 "       // apply offsetmapping\n"
1574 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1575 "#define TexCoord TexCoordOffset\n"
1576 "#endif\n"
1577 "\n"
1578 "       // combine the diffuse textures (base, pants, shirt)\n"
1579 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1580 "#ifdef USEALPHAKILL\n"
1581 "       if (color.a < 0.5)\n"
1582 "               discard;\n"
1583 "#endif\n"
1584 "       color.a *= Alpha;\n"
1585 "#ifdef USECOLORMAPPING\n"
1586 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1587 "#endif\n"
1588 "#ifdef USEVERTEXTEXTUREBLEND\n"
1589 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1590 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1591 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1592 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1593 "       color.a = 1.0;\n"
1594 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1595 "#endif\n"
1596 "\n"
1597 "       // get the surface normal\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1600 "#else\n"
1601 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1602 "#endif\n"
1603 "\n"
1604 "       // get the material colors\n"
1605 "       myhalf3 diffusetex = color.rgb;\n"
1606 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1607 "# ifdef USEVERTEXTEXTUREBLEND\n"
1608 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1609 "# else\n"
1610 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1611 "# endif\n"
1612 "#endif\n"
1613 "\n"
1614 "#ifdef USEREFLECTCUBE\n"
1615 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1616 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1617 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1618 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1619 "#endif\n"
1620 "\n"
1621 "\n"
1622 "\n"
1623 "\n"
1624 "#ifdef MODE_LIGHTSOURCE\n"
1625 "       // light source\n"
1626 "#ifdef USEDIFFUSE\n"
1627 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1628 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1629 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1630 "#ifdef USESPECULAR\n"
1631 "#ifdef USEEXACTSPECULARMATH\n"
1632 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1633 "#else\n"
1634 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1635 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1636 "#endif\n"
1637 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1638 "#endif\n"
1639 "#else\n"
1640 "       color.rgb = diffusetex * Color_Ambient;\n"
1641 "#endif\n"
1642 "       color.rgb *= LightColor;\n"
1643 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1644 "#if defined(USESHADOWMAP2D)\n"
1645 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1646 "#endif\n"
1647 "# ifdef USECUBEFILTER\n"
1648 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1649 "# endif\n"
1650 "#endif // MODE_LIGHTSOURCE\n"
1651 "\n"
1652 "\n"
1653 "\n"
1654 "\n"
1655 "#ifdef MODE_LIGHTDIRECTION\n"
1656 "#define SHADING\n"
1657 "#ifdef USEDIFFUSE\n"
1658 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1659 "#endif\n"
1660 "#define lightcolor LightColor\n"
1661 "#endif // MODE_LIGHTDIRECTION\n"
1662 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1663 "#define SHADING\n"
1664 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1665 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1666 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1667 "       // convert modelspace light vector to tangentspace\n"
1668 "       myhalf3 lightnormal;\n"
1669 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1670 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1671 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1672 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1673 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1674 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1675 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1676 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1677 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1678 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1679 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1680 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1681 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1682 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1683 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1684 "#define SHADING\n"
1685 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1686 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1687 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_FAKELIGHT\n"
1694 "#define SHADING\n"
1695 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1696 "myhalf3 lightcolor = myhalf3(1.0);\n"
1697 "#endif // MODE_FAKELIGHT\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_LIGHTMAP\n"
1703 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1704 "#endif // MODE_LIGHTMAP\n"
1705 "#ifdef MODE_VERTEXCOLOR\n"
1706 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1707 "#endif // MODE_VERTEXCOLOR\n"
1708 "#ifdef MODE_FLATCOLOR\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif // MODE_FLATCOLOR\n"
1711 "\n"
1712 "\n"
1713 "\n"
1714 "\n"
1715 "#ifdef SHADING\n"
1716 "# ifdef USEDIFFUSE\n"
1717 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1718 "#  ifdef USESPECULAR\n"
1719 "#   ifdef USEEXACTSPECULARMATH\n"
1720 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1721 "#   else\n"
1722 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1723 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1724 "#   endif\n"
1725 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1726 "#  else\n"
1727 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1728 "#  endif\n"
1729 "# else\n"
1730 "       color.rgb = diffusetex * Color_Ambient;\n"
1731 "# endif\n"
1732 "#endif\n"
1733 "\n"
1734 "#ifdef USESHADOWMAPORTHO\n"
1735 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1736 "#endif\n"
1737 "\n"
1738 "#ifdef USEDEFERREDLIGHTMAP\n"
1739 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1740 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1741 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1742 "#endif\n"
1743 "\n"
1744 "#ifdef USEGLOW\n"
1745 "#ifdef USEVERTEXTEXTUREBLEND\n"
1746 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1747 "#else\n"
1748 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1749 "#endif\n"
1750 "#endif\n"
1751 "\n"
1752 "#ifdef USEFOG\n"
1753 "       color.rgb = FogVertex(color.rgb);\n"
1754 "#endif\n"
1755 "\n"
1756 "       // 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"
1757 "#ifdef USEREFLECTION\n"
1758 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1759 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1760 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1761 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1762 "       // FIXME temporary hack to detect the case that the reflection\n"
1763 "       // gets blackened at edges due to leaving the area that contains actual\n"
1764 "       // content.\n"
1765 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1766 "       // 'appening.\n"
1767 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1768 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1769 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1770 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1771 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1772 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1773 "#endif\n"
1774 "\n"
1775 "       gl_FragColor = vec4(color);\n"
1776 "}\n"
1777 "#endif // FRAGMENT_SHADER\n"
1778 "\n"
1779 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1780 "#endif // !MODE_DEFERREDGEOMETRY\n"
1781 "#endif // !MODE_WATER\n"
1782 "#endif // !MODE_REFRACTION\n"
1783 "#endif // !MODE_BLOOMBLUR\n"
1784 "#endif // !MODE_GENERIC\n"
1785 "#endif // !MODE_POSTPROCESS\n"
1786 "#endif // !MODE_SHOWDEPTH\n"
1787 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1788 ;
1789
1790 /*
1791 =========================================================================================================================================================
1792
1793
1794
1795 =========================================================================================================================================================
1796
1797
1798
1799 =========================================================================================================================================================
1800
1801
1802
1803 =========================================================================================================================================================
1804
1805
1806
1807 =========================================================================================================================================================
1808
1809
1810
1811 =========================================================================================================================================================
1812
1813
1814
1815 =========================================================================================================================================================
1816 */
1817
1818 const char *builtincgshaderstring =
1819 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1820 "// written by Forest 'LordHavoc' Hale\n"
1821 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1822 "\n"
1823 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1824 "#if defined(USEREFLECTION)\n"
1825 "#undef USESHADOWMAPORTHO\n"
1826 "#endif\n"
1827 "\n"
1828 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1829 "# define USEFOG\n"
1830 "#endif\n"
1831 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1832 "#define USELIGHTMAP\n"
1833 "#endif\n"
1834 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1835 "#define USEEYEVECTOR\n"
1836 "#endif\n"
1837 "\n"
1838 "#ifdef FRAGMENT_SHADER\n"
1839 "#ifdef HLSL\n"
1840 "//#undef USESHADOWMAPPCF\n"
1841 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1842 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1843 "#else\n"
1844 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1845 "#endif\n"
1846 "#endif\n"
1847 "\n"
1848 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1854 "out float4 gl_Position : POSITION,\n"
1855 "out float Depth : TEXCOORD0\n"
1856 ")\n"
1857 "{\n"
1858 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1859 "       Depth = gl_Position.z;\n"
1860 "}\n"
1861 "#endif\n"
1862 "\n"
1863 "#ifdef FRAGMENT_SHADER\n"
1864 "void main\n"
1865 "(\n"
1866 "float Depth : TEXCOORD0,\n"
1867 "out float4 gl_FragColor : COLOR\n"
1868 ")\n"
1869 "{\n"
1870 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1871 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1872 "       temp.yz -= floor(temp.yz);\n"
1873 "       gl_FragColor = temp;\n"
1874 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1875 "}\n"
1876 "#endif\n"
1877 "#else // !MODE_DEPTH_ORSHADOW\n"
1878 "\n"
1879 "\n"
1880 "\n"
1881 "\n"
1882 "#ifdef MODE_SHOWDEPTH\n"
1883 "#ifdef VERTEX_SHADER\n"
1884 "void main\n"
1885 "(\n"
1886 "float4 gl_Vertex : POSITION,\n"
1887 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1888 "out float4 gl_Position : POSITION,\n"
1889 "out float4 gl_FrontColor : COLOR0\n"
1890 ")\n"
1891 "{\n"
1892 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1893 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1894 "}\n"
1895 "#endif\n"
1896 "\n"
1897 "#ifdef FRAGMENT_SHADER\n"
1898 "void main\n"
1899 "(\n"
1900 "float4 gl_FrontColor : COLOR0,\n"
1901 "out float4 gl_FragColor : COLOR\n"
1902 ")\n"
1903 "{\n"
1904 "       gl_FragColor = gl_FrontColor;\n"
1905 "}\n"
1906 "#endif\n"
1907 "#else // !MODE_SHOWDEPTH\n"
1908 "\n"
1909 "\n"
1910 "\n"
1911 "\n"
1912 "#ifdef MODE_POSTPROCESS\n"
1913 "\n"
1914 "#ifdef VERTEX_SHADER\n"
1915 "void main\n"
1916 "(\n"
1917 "float4 gl_Vertex : POSITION,\n"
1918 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1919 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1920 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord1 : TEXCOORD0,\n"
1923 "out float2 TexCoord2 : TEXCOORD1\n"
1924 ")\n"
1925 "{\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1928 "#ifdef USEBLOOM\n"
1929 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1930 "#endif\n"
1931 "}\n"
1932 "#endif\n"
1933 "\n"
1934 "#ifdef FRAGMENT_SHADER\n"
1935 "void main\n"
1936 "(\n"
1937 "float2 TexCoord1 : TEXCOORD0,\n"
1938 "float2 TexCoord2 : TEXCOORD1,\n"
1939 "uniform sampler Texture_First : register(s0),\n"
1940 "#ifdef USEBLOOM\n"
1941 "uniform sampler Texture_Second : register(s1),\n"
1942 "#endif\n"
1943 "#ifdef USEGAMMARAMPS\n"
1944 "uniform sampler Texture_GammaRamps : register(s2),\n"
1945 "#endif\n"
1946 "#ifdef USESATURATION\n"
1947 "uniform float Saturation : register(c30),\n"
1948 "#endif\n"
1949 "#ifdef USEVIEWTINT\n"
1950 "uniform float4 ViewTintColor : register(c41),\n"
1951 "#endif\n"
1952 "uniform float4 UserVec1 : register(c37),\n"
1953 "uniform float4 UserVec2 : register(c38),\n"
1954 "uniform float4 UserVec3 : register(c39),\n"
1955 "uniform float4 UserVec4 : register(c40),\n"
1956 "uniform float ClientTime : register(c2),\n"
1957 "uniform float2 PixelSize : register(c25),\n"
1958 "uniform float4 BloomColorSubtract : register(c43),\n"
1959 "out float4 gl_FragColor : COLOR\n"
1960 ")\n"
1961 "{\n"
1962 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1963 "#ifdef USEBLOOM\n"
1964 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1965 "#endif\n"
1966 "#ifdef USEVIEWTINT\n"
1967 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1968 "#endif\n"
1969 "\n"
1970 "#ifdef USEPOSTPROCESSING\n"
1971 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1972 "// 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"
1973 "       float sobel = 1.0;\n"
1974 "       // float2 ts = textureSize(Texture_First, 0);\n"
1975 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1976 "       float2 px = PixelSize;\n"
1977 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1978 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1979 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1980 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1981 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1982 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1983 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1984 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1985 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1986 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1987 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1988 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1990 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1991 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1992 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1993 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1994 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1995 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1996 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1997 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1998 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1999 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2000 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2001 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2002 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2003 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2004 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2005 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2006 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2007 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2008 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2009 "#endif\n"
2010 "\n"
2011 "#ifdef USESATURATION\n"
2012 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2013 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2014 "       // 'vampire sight' effect, wheres red is compensated\n"
2015 "       #ifdef SATURATION_REDCOMPENSATE\n"
2016 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2017 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2018 "               gl_FragColor.r += r;\n"
2019 "       #else\n"
2020 "               // normal desaturation\n"
2021 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2022 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2023 "       #endif\n"
2024 "#endif\n"
2025 "\n"
2026 "#ifdef USEGAMMARAMPS\n"
2027 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2028 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2029 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2030 "#endif\n"
2031 "}\n"
2032 "#endif\n"
2033 "#else // !MODE_POSTPROCESS\n"
2034 "\n"
2035 "\n"
2036 "\n"
2037 "\n"
2038 "#ifdef MODE_GENERIC\n"
2039 "#ifdef VERTEX_SHADER\n"
2040 "void main\n"
2041 "(\n"
2042 "float4 gl_Vertex : POSITION,\n"
2043 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2044 "float4 gl_Color : COLOR0,\n"
2045 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2046 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2047 "out float4 gl_Position : POSITION,\n"
2048 "#ifdef USEDIFFUSE\n"
2049 "out float2 TexCoord1 : TEXCOORD0,\n"
2050 "#endif\n"
2051 "#ifdef USESPECULAR\n"
2052 "out float2 TexCoord2 : TEXCOORD1,\n"
2053 "#endif\n"
2054 "out float4 gl_FrontColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "#ifdef HLSL\n"
2058 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2059 "#else\n"
2060 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2061 "#endif\n"
2062 "#ifdef USEDIFFUSE\n"
2063 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2064 "#endif\n"
2065 "#ifdef USESPECULAR\n"
2066 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2067 "#endif\n"
2068 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2069 "}\n"
2070 "#endif\n"
2071 "\n"
2072 "#ifdef FRAGMENT_SHADER\n"
2073 "\n"
2074 "void main\n"
2075 "(\n"
2076 "float4 gl_FrontColor : COLOR0,\n"
2077 "float2 TexCoord1 : TEXCOORD0,\n"
2078 "float2 TexCoord2 : TEXCOORD1,\n"
2079 "#ifdef USEDIFFUSE\n"
2080 "uniform sampler Texture_First : register(s0),\n"
2081 "#endif\n"
2082 "#ifdef USESPECULAR\n"
2083 "uniform sampler Texture_Second : register(s1),\n"
2084 "#endif\n"
2085 "out float4 gl_FragColor : COLOR\n"
2086 ")\n"
2087 "{\n"
2088 "       gl_FragColor = gl_FrontColor;\n"
2089 "#ifdef USEDIFFUSE\n"
2090 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2091 "#endif\n"
2092 "\n"
2093 "#ifdef USESPECULAR\n"
2094 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2095 "# ifdef USECOLORMAPPING\n"
2096 "       gl_FragColor *= tex2;\n"
2097 "# endif\n"
2098 "# ifdef USEGLOW\n"
2099 "       gl_FragColor += tex2;\n"
2100 "# endif\n"
2101 "# ifdef USEVERTEXTEXTUREBLEND\n"
2102 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2103 "# endif\n"
2104 "#endif\n"
2105 "}\n"
2106 "#endif\n"
2107 "#else // !MODE_GENERIC\n"
2108 "\n"
2109 "\n"
2110 "\n"
2111 "\n"
2112 "#ifdef MODE_BLOOMBLUR\n"
2113 "#ifdef VERTEX_SHADER\n"
2114 "void main\n"
2115 "(\n"
2116 "float4 gl_Vertex : POSITION,\n"
2117 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2118 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2119 "out float4 gl_Position : POSITION,\n"
2120 "out float2 TexCoord : TEXCOORD0\n"
2121 ")\n"
2122 "{\n"
2123 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2124 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2125 "}\n"
2126 "#endif\n"
2127 "\n"
2128 "#ifdef FRAGMENT_SHADER\n"
2129 "\n"
2130 "void main\n"
2131 "(\n"
2132 "float2 TexCoord : TEXCOORD0,\n"
2133 "uniform sampler Texture_First : register(s0),\n"
2134 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2135 "out float4 gl_FragColor : COLOR\n"
2136 ")\n"
2137 "{\n"
2138 "       int i;\n"
2139 "       float2 tc = TexCoord;\n"
2140 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2141 "       tc += BloomBlur_Parameters.xy;\n"
2142 "       for (i = 1;i < SAMPLES;i++)\n"
2143 "       {\n"
2144 "               color += tex2D(Texture_First, tc).rgb;\n"
2145 "               tc += BloomBlur_Parameters.xy;\n"
2146 "       }\n"
2147 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2148 "}\n"
2149 "#endif\n"
2150 "#else // !MODE_BLOOMBLUR\n"
2151 "#ifdef MODE_REFRACTION\n"
2152 "#ifdef VERTEX_SHADER\n"
2153 "void main\n"
2154 "(\n"
2155 "float4 gl_Vertex : POSITION,\n"
2156 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2157 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2158 "uniform float4x4 TexMatrix : register(c0),\n"
2159 "uniform float3 EyePosition : register(c24),\n"
2160 "out float4 gl_Position : POSITION,\n"
2161 "out float2 TexCoord : TEXCOORD0,\n"
2162 "out float3 EyeVector : TEXCOORD1,\n"
2163 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2164 ")\n"
2165 "{\n"
2166 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2167 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2168 "       ModelViewProjectionPosition = gl_Position;\n"
2169 "}\n"
2170 "#endif\n"
2171 "\n"
2172 "#ifdef FRAGMENT_SHADER\n"
2173 "void main\n"
2174 "(\n"
2175 "float2 TexCoord : TEXCOORD0,\n"
2176 "float3 EyeVector : TEXCOORD1,\n"
2177 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2178 "uniform sampler Texture_Normal : register(s0),\n"
2179 "uniform sampler Texture_Refraction : register(s3),\n"
2180 "uniform sampler Texture_Reflection : register(s7),\n"
2181 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2182 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2183 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2184 "uniform float4 RefractColor : register(c29),\n"
2185 "out float4 gl_FragColor : COLOR\n"
2186 ")\n"
2187 "{\n"
2188 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2189 "       //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"
2190 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2191 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2192 "       // FIXME temporary hack to detect the case that the reflection\n"
2193 "       // gets blackened at edges due to leaving the area that contains actual\n"
2194 "       // content.\n"
2195 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2196 "       // 'appening.\n"
2197 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2198 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2199 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2200 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2201 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2202 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2203 "}\n"
2204 "#endif\n"
2205 "#else // !MODE_REFRACTION\n"
2206 "\n"
2207 "\n"
2208 "\n"
2209 "\n"
2210 "#ifdef MODE_WATER\n"
2211 "#ifdef VERTEX_SHADER\n"
2212 "\n"
2213 "void main\n"
2214 "(\n"
2215 "float4 gl_Vertex : POSITION,\n"
2216 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2217 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2218 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2219 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2220 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2221 "uniform float4x4 TexMatrix : register(c0),\n"
2222 "uniform float3 EyePosition : register(c24),\n"
2223 "out float4 gl_Position : POSITION,\n"
2224 "out float2 TexCoord : TEXCOORD0,\n"
2225 "out float3 EyeVector : TEXCOORD1,\n"
2226 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2227 ")\n"
2228 "{\n"
2229 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2230 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2231 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2232 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2233 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2234 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2235 "       ModelViewProjectionPosition = gl_Position;\n"
2236 "}\n"
2237 "#endif\n"
2238 "\n"
2239 "#ifdef FRAGMENT_SHADER\n"
2240 "void main\n"
2241 "(\n"
2242 "float2 TexCoord : TEXCOORD0,\n"
2243 "float3 EyeVector : TEXCOORD1,\n"
2244 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2245 "uniform sampler Texture_Normal : register(s0),\n"
2246 "uniform sampler Texture_Refraction : register(s3),\n"
2247 "uniform sampler Texture_Reflection : register(s7),\n"
2248 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2249 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2250 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2251 "uniform float4 RefractColor : register(c29),\n"
2252 "uniform float4 ReflectColor : register(c26),\n"
2253 "uniform float ReflectFactor : register(c27),\n"
2254 "uniform float ReflectOffset : register(c28),\n"
2255 "out float4 gl_FragColor : COLOR\n"
2256 ")\n"
2257 "{\n"
2258 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2259 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2260 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2261 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2262 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2263 "       // FIXME temporary hack to detect the case that the reflection\n"
2264 "       // gets blackened at edges due to leaving the area that contains actual\n"
2265 "       // content.\n"
2266 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2267 "       // 'appening.\n"
2268 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2269 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2270 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2271 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2272 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2273 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2274 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2275 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2276 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2277 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2278 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2279 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2280 "}\n"
2281 "#endif\n"
2282 "#else // !MODE_WATER\n"
2283 "\n"
2284 "\n"
2285 "\n"
2286 "\n"
2287 "// 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"
2288 "\n"
2289 "// fragment shader specific:\n"
2290 "#ifdef FRAGMENT_SHADER\n"
2291 "\n"
2292 "#ifdef USEFOG\n"
2293 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2294 "{\n"
2295 "       float fogfrac;\n"
2296 "#ifdef USEFOGHEIGHTTEXTURE\n"
2297 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2298 "       fogfrac = fogheightpixel.a;\n"
2299 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2300 "#else\n"
2301 "# ifdef USEFOGOUTSIDE\n"
2302 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2303 "# else\n"
2304 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2305 "# endif\n"
2306 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2307 "#endif\n"
2308 "}\n"
2309 "#endif\n"
2310 "\n"
2311 "#ifdef USEOFFSETMAPPING\n"
2312 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2313 "{\n"
2314 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2315 "       // 14 sample relief mapping: linear search and then binary search\n"
2316 "       // this basically steps forward a small amount repeatedly until it finds\n"
2317 "       // itself inside solid, then jitters forward and back using decreasing\n"
2318 "       // amounts to find the impact\n"
2319 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2320 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2321 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2322 "       float3 RT = float3(TexCoord, 1);\n"
2323 "       OffsetVector *= 0.1;\n"
2324 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2325 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2328 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2334 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2335 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2336 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2337 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2338 "       return RT.xy;\n"
2339 "#else\n"
2340 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2341 "       // this basically moves forward the full distance, and then backs up based\n"
2342 "       // on height of samples\n"
2343 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2344 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2345 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2346 "       TexCoord += OffsetVector;\n"
2347 "       OffsetVector *= 0.333;\n"
2348 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2349 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2350 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2351 "       return TexCoord;\n"
2352 "#endif\n"
2353 "}\n"
2354 "#endif // USEOFFSETMAPPING\n"
2355 "\n"
2356 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2357 "#if defined(USESHADOWMAP2D)\n"
2358 "# ifdef USESHADOWMAPORTHO\n"
2359 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2360 "# else\n"
2361 "#  ifdef USESHADOWMAPVSDCT\n"
2362 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2363 "{\n"
2364 "       float3 adir = abs(dir);\n"
2365 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2366 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2367 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2368 "}\n"
2369 "#  else\n"
2370 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2371 "{\n"
2372 "       float3 adir = abs(dir);\n"
2373 "       float ma = adir.z;\n"
2374 "       float4 proj = float4(dir, 2.5);\n"
2375 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2376 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2377 "#ifdef HLSL\n"
2378 "       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"
2379 "#else\n"
2380 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2381 "       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"
2382 "#endif\n"
2383 "}\n"
2384 "#  endif\n"
2385 "# endif\n"
2386 "#endif // defined(USESHADOWMAP2D)\n"
2387 "\n"
2388 "# ifdef USESHADOWMAP2D\n"
2389 "#ifdef USESHADOWMAPVSDCT\n"
2390 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2391 "#else\n"
2392 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2393 "#endif\n"
2394 "{\n"
2395 "#ifdef USESHADOWMAPVSDCT\n"
2396 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2397 "#else\n"
2398 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2399 "#endif\n"
2400 "       float f;\n"
2401 "\n"
2402 "#  ifdef USESHADOWSAMPLER\n"
2403 "#    ifdef USESHADOWMAPPCF\n"
2404 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2405 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2406 "       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"
2407 "#    else\n"
2408 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2409 "#    endif\n"
2410 "#  else\n"
2411 "#    ifdef USESHADOWMAPPCF\n"
2412 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2413 "#      ifdef GL_ARB_texture_gather\n"
2414 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2415 "#      else\n"
2416 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2417 "#      endif\n"
2418 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2419 "#      if USESHADOWMAPPCF > 1\n"
2420 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2421 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2422 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2423 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2424 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2425 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2426 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2427 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2428 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2429 "       float4 locols = float4(group1.ab, group3.ab);\n"
2430 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2431 "       locols.yz += group2.ab;\n"
2432 "       hicols.yz += group8.rg;\n"
2433 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2434 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2435 "                               lerp(locols, hicols, offset.y);\n"
2436 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2437 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2438 "       f = dot(cols, float4(1.0/25.0));\n"
2439 "#      else\n"
2440 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2441 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2442 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2443 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2444 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2445 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2446 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2447 "#      endif\n"
2448 "#     else\n"
2449 "#      ifdef GL_EXT_gpu_shader4\n"
2450 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2451 "#      else\n"
2452 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2453 "#      endif\n"
2454 "#      if USESHADOWMAPPCF > 1\n"
2455 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2456 "       center *= ShadowMap_TextureScale;\n"
2457 "       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"
2458 "       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"
2459 "       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"
2460 "       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"
2461 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2462 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2463 "#      else\n"
2464 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2465 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2466 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2467 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2468 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2469 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2470 "#      endif\n"
2471 "#     endif\n"
2472 "#    else\n"
2473 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2474 "#    endif\n"
2475 "#  endif\n"
2476 "#  ifdef USESHADOWMAPORTHO\n"
2477 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2478 "#  else\n"
2479 "       return f;\n"
2480 "#  endif\n"
2481 "}\n"
2482 "# endif\n"
2483 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2484 "#endif // FRAGMENT_SHADER\n"
2485 "\n"
2486 "\n"
2487 "\n"
2488 "\n"
2489 "#ifdef MODE_DEFERREDGEOMETRY\n"
2490 "#ifdef VERTEX_SHADER\n"
2491 "void main\n"
2492 "(\n"
2493 "float4 gl_Vertex : POSITION,\n"
2494 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2495 "#ifdef USEVERTEXTEXTUREBLEND\n"
2496 "float4 gl_Color : COLOR0,\n"
2497 "#endif\n"
2498 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2499 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2500 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2501 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2502 "uniform float4x4 TexMatrix : register(c0),\n"
2503 "#ifdef USEVERTEXTEXTUREBLEND\n"
2504 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2505 "#endif\n"
2506 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2507 "#ifdef USEOFFSETMAPPING\n"
2508 "uniform float3 EyePosition : register(c24),\n"
2509 "#endif\n"
2510 "out float4 gl_Position : POSITION,\n"
2511 "#ifdef USEVERTEXTEXTUREBLEND\n"
2512 "out float4 gl_FrontColor : COLOR,\n"
2513 "#endif\n"
2514 "out float4 TexCoordBoth : TEXCOORD0,\n"
2515 "#ifdef USEOFFSETMAPPING\n"
2516 "out float3 EyeVector : TEXCOORD2,\n"
2517 "#endif\n"
2518 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2519 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2520 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2521 ")\n"
2522 "{\n"
2523 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2524 "#ifdef USEVERTEXTEXTUREBLEND\n"
2525 "#ifdef HLSL\n"
2526 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2527 "#else\n"
2528 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2529 "#endif\n"
2530 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2531 "#endif\n"
2532 "\n"
2533 "       // transform unnormalized eye direction into tangent space\n"
2534 "#ifdef USEOFFSETMAPPING\n"
2535 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2536 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2537 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2538 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2539 "#endif\n"
2540 "\n"
2541 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2542 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2543 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2544 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2545 "       VectorR.w = gl_Position.z;\n"
2546 "}\n"
2547 "#endif // VERTEX_SHADER\n"
2548 "\n"
2549 "#ifdef FRAGMENT_SHADER\n"
2550 "void main\n"
2551 "(\n"
2552 "float4 TexCoordBoth : TEXCOORD0,\n"
2553 "float3 EyeVector : TEXCOORD2,\n"
2554 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2555 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2556 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2557 "uniform sampler Texture_Normal : register(s0),\n"
2558 "#ifdef USEALPHAKILL\n"
2559 "uniform sampler Texture_Color : register(s1),\n"
2560 "#endif\n"
2561 "uniform sampler Texture_Gloss : register(s2),\n"
2562 "#ifdef USEVERTEXTEXTUREBLEND\n"
2563 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2564 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2565 "#endif\n"
2566 "#ifdef USEOFFSETMAPPING\n"
2567 "uniform float OffsetMapping_Scale : register(c24),\n"
2568 "#endif\n"
2569 "uniform half SpecularPower : register(c36),\n"
2570 "#ifdef HLSL\n"
2571 "out float4 gl_FragData0 : COLOR0,\n"
2572 "out float4 gl_FragData1 : COLOR1\n"
2573 "#else\n"
2574 "out float4 gl_FragColor : COLOR\n"
2575 "#endif\n"
2576 ")\n"
2577 "{\n"
2578 "       float2 TexCoord = TexCoordBoth.xy;\n"
2579 "#ifdef USEOFFSETMAPPING\n"
2580 "       // apply offsetmapping\n"
2581 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2582 "#define TexCoord TexCoordOffset\n"
2583 "#endif\n"
2584 "\n"
2585 "#ifdef USEALPHAKILL\n"
2586 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2587 "               discard;\n"
2588 "#endif\n"
2589 "\n"
2590 "#ifdef USEVERTEXTEXTUREBLEND\n"
2591 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2592 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2593 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2594 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2595 "#endif\n"
2596 "\n"
2597 "#ifdef USEVERTEXTEXTUREBLEND\n"
2598 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2599 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2600 "#else\n"
2601 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2602 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2603 "#endif\n"
2604 "\n"
2605 "#ifdef HLSL\n"
2606 "       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"
2607 "       float Depth = VectorR.w / 256.0;\n"
2608 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2609 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2610 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2611 "       gl_FragData1 = depthcolor;\n"
2612 "#else\n"
2613 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2614 "#endif\n"
2615 "}\n"
2616 "#endif // FRAGMENT_SHADER\n"
2617 "#else // !MODE_DEFERREDGEOMETRY\n"
2618 "\n"
2619 "\n"
2620 "\n"
2621 "\n"
2622 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2623 "#ifdef VERTEX_SHADER\n"
2624 "void main\n"
2625 "(\n"
2626 "float4 gl_Vertex : POSITION,\n"
2627 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2628 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2629 "out float4 gl_Position : POSITION,\n"
2630 "out float4 ModelViewPosition : TEXCOORD0\n"
2631 ")\n"
2632 "{\n"
2633 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2634 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2635 "}\n"
2636 "#endif // VERTEX_SHADER\n"
2637 "\n"
2638 "#ifdef FRAGMENT_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "#ifdef HLSL\n"
2642 "float2 Pixel : VPOS,\n"
2643 "#else\n"
2644 "float2 Pixel : WPOS,\n"
2645 "#endif\n"
2646 "float4 ModelViewPosition : TEXCOORD0,\n"
2647 "uniform float4x4 ViewToLight : register(c44),\n"
2648 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2649 "uniform float3 LightPosition : register(c23),\n"
2650 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2651 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2652 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2653 "#ifdef USESPECULAR\n"
2654 "uniform half3 DeferredColor_Specular : register(c11),\n"
2655 "uniform half SpecularPower : register(c36),\n"
2656 "#endif\n"
2657 "uniform sampler Texture_Attenuation : register(s9),\n"
2658 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2659 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2660 "\n"
2661 "#ifdef USECUBEFILTER\n"
2662 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2663 "#endif\n"
2664 "\n"
2665 "#ifdef USESHADOWMAP2D\n"
2666 "# ifdef USESHADOWSAMPLER\n"
2667 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2668 "# else\n"
2669 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2670 "# endif\n"
2671 "#endif\n"
2672 "\n"
2673 "#ifdef USESHADOWMAPVSDCT\n"
2674 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2675 "#endif\n"
2676 "\n"
2677 "#if defined(USESHADOWMAP2D)\n"
2678 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2679 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2680 "#endif\n"
2681 "\n"
2682 "out float4 gl_FragData0 : COLOR0,\n"
2683 "out float4 gl_FragData1 : COLOR1\n"
2684 ")\n"
2685 "{\n"
2686 "       // calculate viewspace pixel position\n"
2687 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2688 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2689 "       float3 position;\n"
2690 "#ifdef HLSL\n"
2691 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2692 "#else\n"
2693 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2694 "#endif\n"
2695 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2696 "       // decode viewspace pixel normal\n"
2697 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2698 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2699 "       // surfacenormal = pixel normal in viewspace\n"
2700 "       // LightVector = pixel to light in viewspace\n"
2701 "       // CubeVector = position in lightspace\n"
2702 "       // eyevector = pixel to view in viewspace\n"
2703 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2704 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2705 "#ifdef USEDIFFUSE\n"
2706 "       // calculate diffuse shading\n"
2707 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2708 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2709 "#endif\n"
2710 "#ifdef USESPECULAR\n"
2711 "       // calculate directional shading\n"
2712 "       float3 eyevector = position * -1.0;\n"
2713 "#  ifdef USEEXACTSPECULARMATH\n"
2714 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2715 "#  else\n"
2716 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2717 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2718 "#  endif\n"
2719 "#endif\n"
2720 "\n"
2721 "#if defined(USESHADOWMAP2D)\n"
2722 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2723 "#ifdef USESHADOWMAPVSDCT\n"
2724 ", Texture_CubeProjection\n"
2725 "#endif\n"
2726 "       ));\n"
2727 "#endif\n"
2728 "\n"
2729 "#ifdef USEDIFFUSE\n"
2730 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2731 "#else\n"
2732 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2733 "#endif\n"
2734 "#ifdef USESPECULAR\n"
2735 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2736 "#else\n"
2737 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2738 "#endif\n"
2739 "\n"
2740 "# ifdef USECUBEFILTER\n"
2741 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2742 "       gl_FragData0.rgb *= cubecolor;\n"
2743 "       gl_FragData1.rgb *= cubecolor;\n"
2744 "# endif\n"
2745 "}\n"
2746 "#endif // FRAGMENT_SHADER\n"
2747 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2748 "\n"
2749 "\n"
2750 "\n"
2751 "\n"
2752 "#ifdef VERTEX_SHADER\n"
2753 "void main\n"
2754 "(\n"
2755 "float4 gl_Vertex : POSITION,\n"
2756 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2757 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2758 "float4 gl_Color : COLOR0,\n"
2759 "#endif\n"
2760 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2761 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2762 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2763 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2764 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2765 "\n"
2766 "uniform float3 EyePosition : register(c24),\n"
2767 "uniform float4x4 TexMatrix : register(c0),\n"
2768 "#ifdef USEVERTEXTEXTUREBLEND\n"
2769 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2770 "#endif\n"
2771 "#ifdef MODE_LIGHTSOURCE\n"
2772 "uniform float4x4 ModelToLight : register(c20),\n"
2773 "#endif\n"
2774 "#ifdef MODE_LIGHTSOURCE\n"
2775 "uniform float3 LightPosition : register(c27),\n"
2776 "#endif\n"
2777 "#ifdef MODE_LIGHTDIRECTION\n"
2778 "uniform float3 LightDir : register(c26),\n"
2779 "#endif\n"
2780 "uniform float4 FogPlane : register(c25),\n"
2781 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2782 "uniform float3 LightPosition : register(c27),\n"
2783 "#endif\n"
2784 "#ifdef USESHADOWMAPORTHO\n"
2785 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2786 "#endif\n"
2787 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2788 "out float4 gl_FrontColor : COLOR,\n"
2789 "#endif\n"
2790 "out float4 TexCoordBoth : TEXCOORD0,\n"
2791 "#ifdef USELIGHTMAP\n"
2792 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2793 "#endif\n"
2794 "#ifdef USEEYEVECTOR\n"
2795 "out float3 EyeVector : TEXCOORD2,\n"
2796 "#endif\n"
2797 "#ifdef USEREFLECTION\n"
2798 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2799 "#endif\n"
2800 "#ifdef USEFOG\n"
2801 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2802 "#endif\n"
2803 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2804 "out float3 LightVector : TEXCOORD1,\n"
2805 "#endif\n"
2806 "#ifdef MODE_LIGHTSOURCE\n"
2807 "out float3 CubeVector : TEXCOORD3,\n"
2808 "#endif\n"
2809 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2810 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2811 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2812 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2813 "#endif\n"
2814 "#ifdef USESHADOWMAPORTHO\n"
2815 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2816 "#endif\n"
2817 "out float4 gl_Position : POSITION\n"
2818 ")\n"
2819 "{\n"
2820 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2821 "#ifdef HLSL\n"
2822 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2823 "#else\n"
2824 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2825 "#endif\n"
2826 "#endif\n"
2827 "       // copy the surface texcoord\n"
2828 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2829 "#ifdef USEVERTEXTEXTUREBLEND\n"
2830 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2831 "#endif\n"
2832 "#ifdef USELIGHTMAP\n"
2833 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2834 "#endif\n"
2835 "\n"
2836 "#ifdef MODE_LIGHTSOURCE\n"
2837 "       // transform vertex position into light attenuation/cubemap space\n"
2838 "       // (-1 to +1 across the light box)\n"
2839 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2840 "\n"
2841 "# ifdef USEDIFFUSE\n"
2842 "       // transform unnormalized light direction into tangent space\n"
2843 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2844 "       //  normalize it per pixel)\n"
2845 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2846 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2847 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2848 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2849 "# endif\n"
2850 "#endif\n"
2851 "\n"
2852 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2853 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2854 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2855 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2856 "#endif\n"
2857 "\n"
2858 "       // transform unnormalized eye direction into tangent space\n"
2859 "#ifdef USEEYEVECTOR\n"
2860 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2861 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2862 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2863 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USEFOG\n"
2867 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2868 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2869 "#endif\n"
2870 "\n"
2871 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2872 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2873 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2874 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2875 "#endif\n"
2876 "\n"
2877 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2878 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2879 "\n"
2880 "#ifdef USESHADOWMAPORTHO\n"
2881 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2882 "#endif\n"
2883 "\n"
2884 "#ifdef USEREFLECTION\n"
2885 "       ModelViewProjectionPosition = gl_Position;\n"
2886 "#endif\n"
2887 "}\n"
2888 "#endif // VERTEX_SHADER\n"
2889 "\n"
2890 "\n"
2891 "\n"
2892 "\n"
2893 "#ifdef FRAGMENT_SHADER\n"
2894 "void main\n"
2895 "(\n"
2896 "#ifdef USEDEFERREDLIGHTMAP\n"
2897 "#ifdef HLSL\n"
2898 "float2 Pixel : VPOS,\n"
2899 "#else\n"
2900 "float2 Pixel : WPOS,\n"
2901 "#endif\n"
2902 "#endif\n"
2903 "float4 gl_FrontColor : COLOR,\n"
2904 "float4 TexCoordBoth : TEXCOORD0,\n"
2905 "#ifdef USELIGHTMAP\n"
2906 "float2 TexCoordLightmap : TEXCOORD1,\n"
2907 "#endif\n"
2908 "#ifdef USEEYEVECTOR\n"
2909 "float3 EyeVector : TEXCOORD2,\n"
2910 "#endif\n"
2911 "#ifdef USEREFLECTION\n"
2912 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2913 "#endif\n"
2914 "#ifdef USEFOG\n"
2915 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2916 "#endif\n"
2917 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2918 "float3 LightVector : TEXCOORD1,\n"
2919 "#endif\n"
2920 "#ifdef MODE_LIGHTSOURCE\n"
2921 "float3 CubeVector : TEXCOORD3,\n"
2922 "#endif\n"
2923 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2924 "float4 ModelViewPosition : TEXCOORD0,\n"
2925 "#endif\n"
2926 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2927 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2928 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2929 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2930 "#endif\n"
2931 "#ifdef USESHADOWMAPORTHO\n"
2932 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2933 "#endif\n"
2934 "\n"
2935 "uniform sampler Texture_Normal : register(s0),\n"
2936 "uniform sampler Texture_Color : register(s1),\n"
2937 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2938 "uniform sampler Texture_Gloss : register(s2),\n"
2939 "#endif\n"
2940 "#ifdef USEGLOW\n"
2941 "uniform sampler Texture_Glow : register(s3),\n"
2942 "#endif\n"
2943 "#ifdef USEVERTEXTEXTUREBLEND\n"
2944 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2945 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2946 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2947 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2948 "#endif\n"
2949 "#ifdef USEGLOW\n"
2950 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2951 "#endif\n"
2952 "#endif\n"
2953 "#ifdef USECOLORMAPPING\n"
2954 "uniform sampler Texture_Pants : register(s4),\n"
2955 "uniform sampler Texture_Shirt : register(s7),\n"
2956 "#endif\n"
2957 "#ifdef USEFOG\n"
2958 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2959 "uniform sampler Texture_FogMask : register(s8),\n"
2960 "#endif\n"
2961 "#ifdef USELIGHTMAP\n"
2962 "uniform sampler Texture_Lightmap : register(s9),\n"
2963 "#endif\n"
2964 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2965 "uniform sampler Texture_Deluxemap : register(s10),\n"
2966 "#endif\n"
2967 "#ifdef USEREFLECTION\n"
2968 "uniform sampler Texture_Reflection : register(s7),\n"
2969 "#endif\n"
2970 "\n"
2971 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2972 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2973 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2974 "#endif\n"
2975 "#ifdef USEDEFERREDLIGHTMAP\n"
2976 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2977 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2978 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2979 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2980 "#endif\n"
2981 "\n"
2982 "#ifdef USECOLORMAPPING\n"
2983 "uniform half3 Color_Pants : register(c7),\n"
2984 "uniform half3 Color_Shirt : register(c8),\n"
2985 "#endif\n"
2986 "#ifdef USEFOG\n"
2987 "uniform float3 FogColor : register(c16),\n"
2988 "uniform float FogRangeRecip : register(c20),\n"
2989 "uniform float FogPlaneViewDist : register(c19),\n"
2990 "uniform float FogHeightFade : register(c17),\n"
2991 "#endif\n"
2992 "\n"
2993 "#ifdef USEOFFSETMAPPING\n"
2994 "uniform float OffsetMapping_Scale : register(c24),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEDEFERREDLIGHTMAP\n"
2998 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2999 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3000 "uniform half3 DeferredMod_Specular : register(c13),\n"
3001 "#endif\n"
3002 "uniform half3 Color_Ambient : register(c3),\n"
3003 "uniform half3 Color_Diffuse : register(c4),\n"
3004 "uniform half3 Color_Specular : register(c5),\n"
3005 "uniform half SpecularPower : register(c36),\n"
3006 "#ifdef USEGLOW\n"
3007 "uniform half3 Color_Glow : register(c6),\n"
3008 "#endif\n"
3009 "uniform half Alpha : register(c0),\n"
3010 "#ifdef USEREFLECTION\n"
3011 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3012 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3013 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3014 "uniform half4 ReflectColor : register(c26),\n"
3015 "#endif\n"
3016 "#ifdef USEREFLECTCUBE\n"
3017 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3018 "uniform sampler Texture_ReflectMask : register(s5),\n"
3019 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3020 "#endif\n"
3021 "#ifdef MODE_LIGHTDIRECTION\n"
3022 "uniform half3 LightColor : register(c21),\n"
3023 "#endif\n"
3024 "#ifdef MODE_LIGHTSOURCE\n"
3025 "uniform half3 LightColor : register(c21),\n"
3026 "#endif\n"
3027 "\n"
3028 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3029 "uniform sampler Texture_Attenuation : register(s9),\n"
3030 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3031 "#endif\n"
3032 "\n"
3033 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3034 "\n"
3035 "#ifdef USESHADOWMAP2D\n"
3036 "# ifdef USESHADOWSAMPLER\n"
3037 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3038 "# else\n"
3039 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3040 "# endif\n"
3041 "#endif\n"
3042 "\n"
3043 "#ifdef USESHADOWMAPVSDCT\n"
3044 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3045 "#endif\n"
3046 "\n"
3047 "#if defined(USESHADOWMAP2D)\n"
3048 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3049 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3050 "#endif\n"
3051 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3052 "\n"
3053 "out float4 gl_FragColor : COLOR\n"
3054 ")\n"
3055 "{\n"
3056 "       float2 TexCoord = TexCoordBoth.xy;\n"
3057 "#ifdef USEVERTEXTEXTUREBLEND\n"
3058 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3059 "#endif\n"
3060 "#ifdef USEOFFSETMAPPING\n"
3061 "       // apply offsetmapping\n"
3062 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3063 "#define TexCoord TexCoordOffset\n"
3064 "#endif\n"
3065 "\n"
3066 "       // combine the diffuse textures (base, pants, shirt)\n"
3067 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3068 "#ifdef USEALPHAKILL\n"
3069 "       if (color.a < 0.5)\n"
3070 "               discard;\n"
3071 "#endif\n"
3072 "       color.a *= Alpha;\n"
3073 "#ifdef USECOLORMAPPING\n"
3074 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3075 "#endif\n"
3076 "#ifdef USEVERTEXTEXTUREBLEND\n"
3077 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3078 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3079 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3080 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3081 "       color.a = 1.0;\n"
3082 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3083 "#endif\n"
3084 "\n"
3085 "       // get the surface normal\n"
3086 "#ifdef USEVERTEXTEXTUREBLEND\n"
3087 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3088 "#else\n"
3089 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3090 "#endif\n"
3091 "\n"
3092 "       // get the material colors\n"
3093 "       half3 diffusetex = color.rgb;\n"
3094 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3095 "# ifdef USEVERTEXTEXTUREBLEND\n"
3096 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3097 "# else\n"
3098 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3099 "# endif\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef USEREFLECTCUBE\n"
3103 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3104 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3105 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3106 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3107 "#endif\n"
3108 "\n"
3109 "\n"
3110 "\n"
3111 "\n"
3112 "#ifdef MODE_LIGHTSOURCE\n"
3113 "       // light source\n"
3114 "#ifdef USEDIFFUSE\n"
3115 "       half3 lightnormal = half3(normalize(LightVector));\n"
3116 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3117 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3118 "#ifdef USESPECULAR\n"
3119 "#ifdef USEEXACTSPECULARMATH\n"
3120 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3121 "#else\n"
3122 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3123 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3124 "#endif\n"
3125 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3126 "#endif\n"
3127 "#else\n"
3128 "       color.rgb = diffusetex * Color_Ambient;\n"
3129 "#endif\n"
3130 "       color.rgb *= LightColor;\n"
3131 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3132 "#if defined(USESHADOWMAP2D)\n"
3133 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3134 "#ifdef USESHADOWMAPVSDCT\n"
3135 ", Texture_CubeProjection\n"
3136 "#endif\n"
3137 "       ));\n"
3138 "\n"
3139 "#endif\n"
3140 "# ifdef USECUBEFILTER\n"
3141 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3142 "# endif\n"
3143 "\n"
3144 "#ifdef USESHADOWMAP2D\n"
3145 "#ifdef USESHADOWMAPVSDCT\n"
3146 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3147 "#else\n"
3148 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3149 "#endif\n"
3150 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3151 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3152 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3153 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3154 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3155 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3156 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3157 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3158 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3159 "//     color.r = half(shadowmaptc.z);\n"
3160 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3161 "//     color.r = half(shadowmaptc.z);\n"
3162 "//     color.r = 1;\n"
3163 "//     color.rgb = abs(CubeVector);\n"
3164 "#endif\n"
3165 "//     color.rgb = half3(1,1,1);\n"
3166 "#endif // MODE_LIGHTSOURCE\n"
3167 "\n"
3168 "\n"
3169 "\n"
3170 "\n"
3171 "#ifdef MODE_LIGHTDIRECTION\n"
3172 "#define SHADING\n"
3173 "#ifdef USEDIFFUSE\n"
3174 "       half3 lightnormal = half3(normalize(LightVector));\n"
3175 "#endif\n"
3176 "#define lightcolor LightColor\n"
3177 "#endif // MODE_LIGHTDIRECTION\n"
3178 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3179 "#define SHADING\n"
3180 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3181 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3182 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3183 "       // convert modelspace light vector to tangentspace\n"
3184 "       half3 lightnormal;\n"
3185 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3186 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3187 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3188 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3189 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3190 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3191 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3192 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3193 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3194 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3195 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3196 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3197 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3198 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3199 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3200 "#define SHADING\n"
3201 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3202 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3203 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3204 "#endif\n"
3205 "\n"
3206 "\n"
3207 "\n"
3208 "\n"
3209 "#ifdef MODE_FAKELIGHT\n"
3210 "#define SHADING\n"
3211 "half3 lightnormal = half3(normalize(EyeVector));\n"
3212 "half3 lightcolor = half3(1.0);\n"
3213 "#endif // MODE_FAKELIGHT\n"
3214 "\n"
3215 "\n"
3216 "\n"
3217 "\n"
3218 "#ifdef MODE_LIGHTMAP\n"
3219 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3220 "#endif // MODE_LIGHTMAP\n"
3221 "#ifdef MODE_VERTEXCOLOR\n"
3222 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3223 "#endif // MODE_VERTEXCOLOR\n"
3224 "#ifdef MODE_FLATCOLOR\n"
3225 "       color.rgb = diffusetex * Color_Ambient;\n"
3226 "#endif // MODE_FLATCOLOR\n"
3227 "\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "#ifdef SHADING\n"
3232 "# ifdef USEDIFFUSE\n"
3233 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3234 "#  ifdef USESPECULAR\n"
3235 "#   ifdef USEEXACTSPECULARMATH\n"
3236 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3237 "#   else\n"
3238 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3239 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3240 "#   endif\n"
3241 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3242 "#  else\n"
3243 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3244 "#  endif\n"
3245 "# else\n"
3246 "       color.rgb = diffusetex * Color_Ambient;\n"
3247 "# endif\n"
3248 "#endif\n"
3249 "\n"
3250 "#ifdef USESHADOWMAPORTHO\n"
3251 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3252 "#endif\n"
3253 "\n"
3254 "#ifdef USEDEFERREDLIGHTMAP\n"
3255 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3256 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3257 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3258 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3259 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3260 "#endif\n"
3261 "\n"
3262 "#ifdef USEGLOW\n"
3263 "#ifdef USEVERTEXTEXTUREBLEND\n"
3264 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3265 "#else\n"
3266 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3267 "#endif\n"
3268 "#endif\n"
3269 "\n"
3270 "#ifdef USEFOG\n"
3271 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3272 "#endif\n"
3273 "\n"
3274 "       // 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"
3275 "#ifdef USEREFLECTION\n"
3276 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3277 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3278 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3279 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3280 "       // FIXME temporary hack to detect the case that the reflection\n"
3281 "       // gets blackened at edges due to leaving the area that contains actual\n"
3282 "       // content.\n"
3283 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3284 "       // 'appening.\n"
3285 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3286 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3287 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3288 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3289 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3290 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3291 "#endif\n"
3292 "\n"
3293 "       gl_FragColor = float4(color);\n"
3294 "}\n"
3295 "#endif // FRAGMENT_SHADER\n"
3296 "\n"
3297 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3298 "#endif // !MODE_DEFERREDGEOMETRY\n"
3299 "#endif // !MODE_WATER\n"
3300 "#endif // !MODE_REFRACTION\n"
3301 "#endif // !MODE_BLOOMBLUR\n"
3302 "#endif // !MODE_GENERIC\n"
3303 "#endif // !MODE_POSTPROCESS\n"
3304 "#endif // !MODE_SHOWDEPTH\n"
3305 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3306 ;
3307
3308 char *glslshaderstring = NULL;
3309 char *cgshaderstring = NULL;
3310 char *hlslshaderstring = NULL;
3311
3312 //=======================================================================================================================================================
3313
3314 typedef struct shaderpermutationinfo_s
3315 {
3316         const char *pretext;
3317         const char *name;
3318 }
3319 shaderpermutationinfo_t;
3320
3321 typedef struct shadermodeinfo_s
3322 {
3323         const char *vertexfilename;
3324         const char *geometryfilename;
3325         const char *fragmentfilename;
3326         const char *pretext;
3327         const char *name;
3328 }
3329 shadermodeinfo_t;
3330
3331 typedef enum shaderpermutation_e
3332 {
3333         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3334         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3335         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3336         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3337         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3338         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3339         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3340         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3341         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3342         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3343         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3344         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3345         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3346         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3347         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3348         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3349         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3350         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3351         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3352         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3353         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3354         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3355         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3356         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3357         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3358         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3359         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3360         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3361         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3362 }
3363 shaderpermutation_t;
3364
3365 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3366 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3367 {
3368         {"#define USEDIFFUSE\n", " diffuse"},
3369         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3370         {"#define USEVIEWTINT\n", " viewtint"},
3371         {"#define USECOLORMAPPING\n", " colormapping"},
3372         {"#define USESATURATION\n", " saturation"},
3373         {"#define USEFOGINSIDE\n", " foginside"},
3374         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3375         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3376         {"#define USEGAMMARAMPS\n", " gammaramps"},
3377         {"#define USECUBEFILTER\n", " cubefilter"},
3378         {"#define USEGLOW\n", " glow"},
3379         {"#define USEBLOOM\n", " bloom"},
3380         {"#define USESPECULAR\n", " specular"},
3381         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3382         {"#define USEREFLECTION\n", " reflection"},
3383         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3384         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3385         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3386         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3387         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3388         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3389         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3390         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3391         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3392         {"#define USEALPHAKILL\n", " alphakill"},
3393         {"#define USEREFLECTCUBE\n", " reflectcube"},
3394         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3395 };
3396
3397 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3398 typedef enum shadermode_e
3399 {
3400         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3401         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3402         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3403         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3404         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3405         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3406         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3407         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3408         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3409         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3410         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3411         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3412         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3413         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3414         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3415         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3416         SHADERMODE_COUNT
3417 }
3418 shadermode_t;
3419
3420 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3421 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3422 {
3423         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3424         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3425         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3439 };
3440
3441 #ifdef SUPPORTCG
3442 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3443 {
3444         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3445         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3446         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3447         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3448         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3449         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3460 };
3461 #endif
3462
3463 #ifdef SUPPORTD3D
3464 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3465 {
3466         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3467         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3468         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3469         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3475         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3476         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3481 };
3482 #endif
3483
3484 struct r_glsl_permutation_s;
3485 typedef struct r_glsl_permutation_s
3486 {
3487         /// hash lookup data
3488         struct r_glsl_permutation_s *hashnext;
3489         unsigned int mode;
3490         unsigned int permutation;
3491
3492         /// indicates if we have tried compiling this permutation already
3493         qboolean compiled;
3494         /// 0 if compilation failed
3495         int program;
3496         /// locations of detected uniforms in program object, or -1 if not found
3497         int loc_Texture_First;
3498         int loc_Texture_Second;
3499         int loc_Texture_GammaRamps;
3500         int loc_Texture_Normal;
3501         int loc_Texture_Color;
3502         int loc_Texture_Gloss;
3503         int loc_Texture_Glow;
3504         int loc_Texture_SecondaryNormal;
3505         int loc_Texture_SecondaryColor;
3506         int loc_Texture_SecondaryGloss;
3507         int loc_Texture_SecondaryGlow;
3508         int loc_Texture_Pants;
3509         int loc_Texture_Shirt;
3510         int loc_Texture_FogHeightTexture;
3511         int loc_Texture_FogMask;
3512         int loc_Texture_Lightmap;
3513         int loc_Texture_Deluxemap;
3514         int loc_Texture_Attenuation;
3515         int loc_Texture_Cube;
3516         int loc_Texture_Refraction;
3517         int loc_Texture_Reflection;
3518         int loc_Texture_ShadowMap2D;
3519         int loc_Texture_CubeProjection;
3520         int loc_Texture_ScreenDepth;
3521         int loc_Texture_ScreenNormalMap;
3522         int loc_Texture_ScreenDiffuse;
3523         int loc_Texture_ScreenSpecular;
3524         int loc_Texture_ReflectMask;
3525         int loc_Texture_ReflectCube;
3526         int loc_Alpha;
3527         int loc_BloomBlur_Parameters;
3528         int loc_ClientTime;
3529         int loc_Color_Ambient;
3530         int loc_Color_Diffuse;
3531         int loc_Color_Specular;
3532         int loc_Color_Glow;
3533         int loc_Color_Pants;
3534         int loc_Color_Shirt;
3535         int loc_DeferredColor_Ambient;
3536         int loc_DeferredColor_Diffuse;
3537         int loc_DeferredColor_Specular;
3538         int loc_DeferredMod_Diffuse;
3539         int loc_DeferredMod_Specular;
3540         int loc_DistortScaleRefractReflect;
3541         int loc_EyePosition;
3542         int loc_FogColor;
3543         int loc_FogHeightFade;
3544         int loc_FogPlane;
3545         int loc_FogPlaneViewDist;
3546         int loc_FogRangeRecip;
3547         int loc_LightColor;
3548         int loc_LightDir;
3549         int loc_LightPosition;
3550         int loc_OffsetMapping_Scale;
3551         int loc_PixelSize;
3552         int loc_ReflectColor;
3553         int loc_ReflectFactor;
3554         int loc_ReflectOffset;
3555         int loc_RefractColor;
3556         int loc_Saturation;
3557         int loc_ScreenCenterRefractReflect;
3558         int loc_ScreenScaleRefractReflect;
3559         int loc_ScreenToDepth;
3560         int loc_ShadowMap_Parameters;
3561         int loc_ShadowMap_TextureScale;
3562         int loc_SpecularPower;
3563         int loc_UserVec1;
3564         int loc_UserVec2;
3565         int loc_UserVec3;
3566         int loc_UserVec4;
3567         int loc_ViewTintColor;
3568         int loc_ViewToLight;
3569         int loc_ModelToLight;
3570         int loc_TexMatrix;
3571         int loc_BackgroundTexMatrix;
3572         int loc_ModelViewProjectionMatrix;
3573         int loc_ModelViewMatrix;
3574         int loc_PixelToScreenTexCoord;
3575         int loc_ModelToReflectCube;
3576         int loc_ShadowMapMatrix;
3577         int loc_BloomColorSubtract;
3578         int loc_NormalmapScrollBlend;
3579 }
3580 r_glsl_permutation_t;
3581
3582 #define SHADERPERMUTATION_HASHSIZE 256
3583
3584
3585 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3586 // these can NOT degrade! only use for simple stuff
3587 enum
3588 {
3589         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3590         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3591 };
3592 #define SHADERSTATICPARMS_COUNT 2
3593
3594 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3595 static int shaderstaticparms_count = 0;
3596
3597 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3598 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3599 qboolean R_CompileShader_CheckStaticParms(void)
3600 {
3601         static int r_compileshader_staticparms_save[1];
3602         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3603         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3604
3605         // detect all
3606         if (r_glsl_saturation_redcompensate.integer)
3607                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3608         if(r_shadow_glossexact.integer)
3609                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3610
3611         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3612 }
3613
3614 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3615         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3616                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3617         else \
3618                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3619 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3620 {
3621         shaderstaticparms_count = 0;
3622
3623         // emit all
3624         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3625         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3626 }
3627
3628
3629 /// information about each possible shader permutation
3630 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3631 /// currently selected permutation
3632 r_glsl_permutation_t *r_glsl_permutation;
3633 /// storage for permutations linked in the hash table
3634 memexpandablearray_t r_glsl_permutationarray;
3635
3636 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3637 {
3638         //unsigned int hashdepth = 0;
3639         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3640         r_glsl_permutation_t *p;
3641         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3642         {
3643                 if (p->mode == mode && p->permutation == permutation)
3644                 {
3645                         //if (hashdepth > 10)
3646                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3647                         return p;
3648                 }
3649                 //hashdepth++;
3650         }
3651         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3652         p->mode = mode;
3653         p->permutation = permutation;
3654         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3655         r_glsl_permutationhash[mode][hashindex] = p;
3656         //if (hashdepth > 10)
3657         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3658         return p;
3659 }
3660
3661 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3662 {
3663         char *shaderstring;
3664         if (!filename || !filename[0])
3665                 return NULL;
3666         if (!strcmp(filename, "glsl/default.glsl"))
3667         {
3668                 if (!glslshaderstring)
3669                 {
3670                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3671                         if (glslshaderstring)
3672                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3673                         else
3674                                 glslshaderstring = (char *)builtinshaderstring;
3675                 }
3676                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3677                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3678                 return shaderstring;
3679         }
3680         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3681         if (shaderstring)
3682         {
3683                 if (printfromdisknotice)
3684                         Con_DPrintf("from disk %s... ", filename);
3685                 return shaderstring;
3686         }
3687         return shaderstring;
3688 }
3689
3690 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3691 {
3692         int i;
3693         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3694         char *vertexstring, *geometrystring, *fragmentstring;
3695         char permutationname[256];
3696         int vertstrings_count = 0;
3697         int geomstrings_count = 0;
3698         int fragstrings_count = 0;
3699         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3701         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3702
3703         if (p->compiled)
3704                 return;
3705         p->compiled = true;
3706         p->program = 0;
3707
3708         permutationname[0] = 0;
3709         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3710         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3711         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3712
3713         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3714
3715         // the first pretext is which type of shader to compile as
3716         // (later these will all be bound together as a program object)
3717         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3718         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3719         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3720
3721         // the second pretext is the mode (for example a light source)
3722         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3723         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3724         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3725         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3726
3727         // now add all the permutation pretexts
3728         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3729         {
3730                 if (permutation & (1<<i))
3731                 {
3732                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3733                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3734                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3735                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3736                 }
3737                 else
3738                 {
3739                         // keep line numbers correct
3740                         vertstrings_list[vertstrings_count++] = "\n";
3741                         geomstrings_list[geomstrings_count++] = "\n";
3742                         fragstrings_list[fragstrings_count++] = "\n";
3743                 }
3744         }
3745
3746         // add static parms
3747         R_CompileShader_AddStaticParms(mode, permutation);
3748         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3749         vertstrings_count += shaderstaticparms_count;
3750         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3751         geomstrings_count += shaderstaticparms_count;
3752         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3753         fragstrings_count += shaderstaticparms_count;
3754
3755         // now append the shader text itself
3756         vertstrings_list[vertstrings_count++] = vertexstring;
3757         geomstrings_list[geomstrings_count++] = geometrystring;
3758         fragstrings_list[fragstrings_count++] = fragmentstring;
3759
3760         // if any sources were NULL, clear the respective list
3761         if (!vertexstring)
3762                 vertstrings_count = 0;
3763         if (!geometrystring)
3764                 geomstrings_count = 0;
3765         if (!fragmentstring)
3766                 fragstrings_count = 0;
3767
3768         // compile the shader program
3769         if (vertstrings_count + geomstrings_count + fragstrings_count)
3770                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3771         if (p->program)
3772         {
3773                 CHECKGLERROR
3774                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3775                 // look up all the uniform variable names we care about, so we don't
3776                 // have to look them up every time we set them
3777
3778                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3779                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3780                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3781                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3782                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3783                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3784                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3785                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3786                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3787                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3788                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3789                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3790                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3791                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3792                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3793                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3794                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3795                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3796                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3797                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3798                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3799                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3800                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3801                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3802                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3803                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3804                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3805                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3806                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3807                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3808                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3809                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3810                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3811                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3812                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3813                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3814                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3815                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3816                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3817                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3818                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3819                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3820                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3821                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3822                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3823                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3824                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3825                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3826                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3827                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3828                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3829                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3830                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3831                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3832                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3833                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3834                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3835                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3836                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3837                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3838                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3839                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3840                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3841                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3842                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3843                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3844                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3845                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3846                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3847                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3848                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3849                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3850                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3851                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3852                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3853                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3854                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3855                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3856                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3857                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3858                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3859                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3860                 // initialize the samplers to refer to the texture units we use
3861                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3862                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3863                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3864                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3865                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3866                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3867                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3868                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3869                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3870                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3871                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3872                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3873                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3874                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3875                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3876                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3877                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3878                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3879                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3880                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3881                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3882                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3883                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3884                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3885                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3886                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3887                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3888                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3889                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3890                 CHECKGLERROR
3891                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3892         }
3893         else
3894                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3895
3896         // free the strings
3897         if (vertexstring)
3898                 Mem_Free(vertexstring);
3899         if (geometrystring)
3900                 Mem_Free(geometrystring);
3901         if (fragmentstring)
3902                 Mem_Free(fragmentstring);
3903 }
3904
3905 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3906 {
3907         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3908         if (r_glsl_permutation != perm)
3909         {
3910                 r_glsl_permutation = perm;
3911                 if (!r_glsl_permutation->program)
3912                 {
3913                         if (!r_glsl_permutation->compiled)
3914                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3915                         if (!r_glsl_permutation->program)
3916                         {
3917                                 // remove features until we find a valid permutation
3918                                 int i;
3919                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3920                                 {
3921                                         // reduce i more quickly whenever it would not remove any bits
3922                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3923                                         if (!(permutation & j))
3924                                                 continue;
3925                                         permutation -= j;
3926                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3927                                         if (!r_glsl_permutation->compiled)
3928                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3929                                         if (r_glsl_permutation->program)
3930                                                 break;
3931                                 }
3932                                 if (i >= SHADERPERMUTATION_COUNT)
3933                                 {
3934                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3935                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3936                                         qglUseProgramObjectARB(0);CHECKGLERROR
3937                                         return; // no bit left to clear, entire mode is broken
3938                                 }
3939                         }
3940                 }
3941                 CHECKGLERROR
3942                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3943         }
3944         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3945         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3946         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3947 }
3948
3949 #ifdef SUPPORTCG
3950 #include <Cg/cgGL.h>
3951 struct r_cg_permutation_s;
3952 typedef struct r_cg_permutation_s
3953 {
3954         /// hash lookup data
3955         struct r_cg_permutation_s *hashnext;
3956         unsigned int mode;
3957         unsigned int permutation;
3958
3959         /// indicates if we have tried compiling this permutation already
3960         qboolean compiled;
3961         /// 0 if compilation failed
3962         CGprogram vprogram;
3963         CGprogram fprogram;
3964         /// locations of detected parameters in programs, or NULL if not found
3965         CGparameter vp_EyePosition;
3966         CGparameter vp_FogPlane;
3967         CGparameter vp_LightDir;
3968         CGparameter vp_LightPosition;
3969         CGparameter vp_ModelToLight;
3970         CGparameter vp_TexMatrix;
3971         CGparameter vp_BackgroundTexMatrix;
3972         CGparameter vp_ModelViewProjectionMatrix;
3973         CGparameter vp_ModelViewMatrix;
3974         CGparameter vp_ShadowMapMatrix;
3975
3976         CGparameter fp_Texture_First;
3977         CGparameter fp_Texture_Second;
3978         CGparameter fp_Texture_GammaRamps;
3979         CGparameter fp_Texture_Normal;
3980         CGparameter fp_Texture_Color;
3981         CGparameter fp_Texture_Gloss;
3982         CGparameter fp_Texture_Glow;
3983         CGparameter fp_Texture_SecondaryNormal;
3984         CGparameter fp_Texture_SecondaryColor;
3985         CGparameter fp_Texture_SecondaryGloss;
3986         CGparameter fp_Texture_SecondaryGlow;
3987         CGparameter fp_Texture_Pants;
3988         CGparameter fp_Texture_Shirt;
3989         CGparameter fp_Texture_FogHeightTexture;
3990         CGparameter fp_Texture_FogMask;
3991         CGparameter fp_Texture_Lightmap;
3992         CGparameter fp_Texture_Deluxemap;
3993         CGparameter fp_Texture_Attenuation;
3994         CGparameter fp_Texture_Cube;
3995         CGparameter fp_Texture_Refraction;
3996         CGparameter fp_Texture_Reflection;
3997         CGparameter fp_Texture_ShadowMap2D;
3998         CGparameter fp_Texture_CubeProjection;
3999         CGparameter fp_Texture_ScreenDepth;
4000         CGparameter fp_Texture_ScreenNormalMap;
4001         CGparameter fp_Texture_ScreenDiffuse;
4002         CGparameter fp_Texture_ScreenSpecular;
4003         CGparameter fp_Texture_ReflectMask;
4004         CGparameter fp_Texture_ReflectCube;
4005         CGparameter fp_Alpha;
4006         CGparameter fp_BloomBlur_Parameters;
4007         CGparameter fp_ClientTime;
4008         CGparameter fp_Color_Ambient;
4009         CGparameter fp_Color_Diffuse;
4010         CGparameter fp_Color_Specular;
4011         CGparameter fp_Color_Glow;
4012         CGparameter fp_Color_Pants;
4013         CGparameter fp_Color_Shirt;
4014         CGparameter fp_DeferredColor_Ambient;
4015         CGparameter fp_DeferredColor_Diffuse;
4016         CGparameter fp_DeferredColor_Specular;
4017         CGparameter fp_DeferredMod_Diffuse;
4018         CGparameter fp_DeferredMod_Specular;
4019         CGparameter fp_DistortScaleRefractReflect;
4020         CGparameter fp_EyePosition;
4021         CGparameter fp_FogColor;
4022         CGparameter fp_FogHeightFade;
4023         CGparameter fp_FogPlane;
4024         CGparameter fp_FogPlaneViewDist;
4025         CGparameter fp_FogRangeRecip;
4026         CGparameter fp_LightColor;
4027         CGparameter fp_LightDir;
4028         CGparameter fp_LightPosition;
4029         CGparameter fp_OffsetMapping_Scale;
4030         CGparameter fp_PixelSize;
4031         CGparameter fp_ReflectColor;
4032         CGparameter fp_ReflectFactor;
4033         CGparameter fp_ReflectOffset;
4034         CGparameter fp_RefractColor;
4035         CGparameter fp_Saturation;
4036         CGparameter fp_ScreenCenterRefractReflect;
4037         CGparameter fp_ScreenScaleRefractReflect;
4038         CGparameter fp_ScreenToDepth;
4039         CGparameter fp_ShadowMap_Parameters;
4040         CGparameter fp_ShadowMap_TextureScale;
4041         CGparameter fp_SpecularPower;
4042         CGparameter fp_UserVec1;
4043         CGparameter fp_UserVec2;
4044         CGparameter fp_UserVec3;
4045         CGparameter fp_UserVec4;
4046         CGparameter fp_ViewTintColor;
4047         CGparameter fp_ViewToLight;
4048         CGparameter fp_PixelToScreenTexCoord;
4049         CGparameter fp_ModelToReflectCube;
4050         CGparameter fp_BloomColorSubtract;
4051         CGparameter fp_NormalmapScrollBlend;
4052 }
4053 r_cg_permutation_t;
4054
4055 /// information about each possible shader permutation
4056 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4057 /// currently selected permutation
4058 r_cg_permutation_t *r_cg_permutation;
4059 /// storage for permutations linked in the hash table
4060 memexpandablearray_t r_cg_permutationarray;
4061
4062 #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));}}
4063
4064 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4065 {
4066         //unsigned int hashdepth = 0;
4067         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4068         r_cg_permutation_t *p;
4069         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4070         {
4071                 if (p->mode == mode && p->permutation == permutation)
4072                 {
4073                         //if (hashdepth > 10)
4074                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4075                         return p;
4076                 }
4077                 //hashdepth++;
4078         }
4079         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4080         p->mode = mode;
4081         p->permutation = permutation;
4082         p->hashnext = r_cg_permutationhash[mode][hashindex];
4083         r_cg_permutationhash[mode][hashindex] = p;
4084         //if (hashdepth > 10)
4085         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4086         return p;
4087 }
4088
4089 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4090 {
4091         char *shaderstring;
4092         if (!filename || !filename[0])
4093                 return NULL;
4094         if (!strcmp(filename, "cg/default.cg"))
4095         {
4096                 if (!cgshaderstring)
4097                 {
4098                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4099                         if (cgshaderstring)
4100                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4101                         else
4102                                 cgshaderstring = (char *)builtincgshaderstring;
4103                 }
4104                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4105                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4106                 return shaderstring;
4107         }
4108         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4109         if (shaderstring)
4110         {
4111                 if (printfromdisknotice)
4112                         Con_DPrintf("from disk %s... ", filename);
4113                 return shaderstring;
4114         }
4115         return shaderstring;
4116 }
4117
4118 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4119 {
4120         // TODO: load or create .fp and .vp shader files
4121 }
4122
4123 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4124 {
4125         int i;
4126         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4127         int vertstring_length = 0;
4128         int geomstring_length = 0;
4129         int fragstring_length = 0;
4130         char *t;
4131         char *vertexstring, *geometrystring, *fragmentstring;
4132         char *vertstring, *geomstring, *fragstring;
4133         char permutationname[256];
4134         char cachename[256];
4135         CGprofile vertexProfile;
4136         CGprofile fragmentProfile;
4137         int vertstrings_count = 0;
4138         int geomstrings_count = 0;
4139         int fragstrings_count = 0;
4140         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4141         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4142         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4143
4144         if (p->compiled)
4145                 return;
4146         p->compiled = true;
4147         p->vprogram = NULL;
4148         p->fprogram = NULL;
4149
4150         permutationname[0] = 0;
4151         cachename[0] = 0;
4152         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4153         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4154         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4155
4156         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4157         strlcat(cachename, "cg/", sizeof(cachename));
4158
4159         // the first pretext is which type of shader to compile as
4160         // (later these will all be bound together as a program object)
4161         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4162         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4163         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4164
4165         // the second pretext is the mode (for example a light source)
4166         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4167         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4168         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4169         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4170         strlcat(cachename, modeinfo->name, sizeof(cachename));
4171
4172         // now add all the permutation pretexts
4173         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4174         {
4175                 if (permutation & (1<<i))
4176                 {
4177                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4178                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4179                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4180                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4181                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4182                 }
4183                 else
4184                 {
4185                         // keep line numbers correct
4186                         vertstrings_list[vertstrings_count++] = "\n";
4187                         geomstrings_list[geomstrings_count++] = "\n";
4188                         fragstrings_list[fragstrings_count++] = "\n";
4189                 }
4190         }
4191
4192         // add static parms
4193         R_CompileShader_AddStaticParms(mode, permutation);
4194         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4195         vertstrings_count += shaderstaticparms_count;
4196         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4197         geomstrings_count += shaderstaticparms_count;
4198         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4199         fragstrings_count += shaderstaticparms_count;
4200
4201         // replace spaces in the cachename with _ characters
4202         for (i = 0;cachename[i];i++)
4203                 if (cachename[i] == ' ')
4204                         cachename[i] = '_';
4205
4206         // now append the shader text itself
4207         vertstrings_list[vertstrings_count++] = vertexstring;
4208         geomstrings_list[geomstrings_count++] = geometrystring;
4209         fragstrings_list[fragstrings_count++] = fragmentstring;
4210
4211         // if any sources were NULL, clear the respective list
4212         if (!vertexstring)
4213                 vertstrings_count = 0;
4214         if (!geometrystring)
4215                 geomstrings_count = 0;
4216         if (!fragmentstring)
4217                 fragstrings_count = 0;
4218
4219         vertstring_length = 0;
4220         for (i = 0;i < vertstrings_count;i++)
4221                 vertstring_length += strlen(vertstrings_list[i]);
4222         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4223         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4224                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4225
4226         geomstring_length = 0;
4227         for (i = 0;i < geomstrings_count;i++)
4228                 geomstring_length += strlen(geomstrings_list[i]);
4229         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4230         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4231                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4232
4233         fragstring_length = 0;
4234         for (i = 0;i < fragstrings_count;i++)
4235                 fragstring_length += strlen(fragstrings_list[i]);
4236         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4237         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4238                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4239
4240         CHECKGLERROR
4241         CHECKCGERROR
4242         //vertexProfile = CG_PROFILE_ARBVP1;
4243         //fragmentProfile = CG_PROFILE_ARBFP1;
4244         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4245         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4246         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4247         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4248         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4249         CHECKGLERROR
4250
4251         // try to load the cached shader, or generate one
4252         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4253
4254         // if caching failed, do a dynamic compile for now
4255         CHECKCGERROR
4256         if (vertstring[0] && !p->vprogram)
4257                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4258         CHECKCGERROR
4259         if (fragstring[0] && !p->fprogram)
4260                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4261         CHECKCGERROR
4262
4263         // look up all the uniform variable names we care about, so we don't
4264         // have to look them up every time we set them
4265         if (p->vprogram)
4266         {
4267                 CHECKCGERROR
4268                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4269                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4270                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4271                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4272                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4273                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4274                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4275                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4276                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4277                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4278                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4279                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4280                 CHECKCGERROR
4281         }
4282         if (p->fprogram)
4283         {
4284                 CHECKCGERROR
4285                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4286                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4287                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4288                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4289                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4290                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4291                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4292                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4293                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4294                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4295                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4296                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4297                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4298                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4299                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4300                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4301                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4302                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4303                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4304                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4305                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4306                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4307                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4308                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4309                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4310                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4311                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4312                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4313                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4314                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4315                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4316                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4317                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4318                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4319                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4320                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4321                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4322                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4323                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4324                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4325                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4326                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4327                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4328                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4329                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4330                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4331                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4332                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4333                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4334                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4335                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4336                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4337                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4338                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4339                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4340                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4341                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4342                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4343                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4344                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4345                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4346                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4347                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4348                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4349                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4350                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4351                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4352                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4353                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4354                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4355                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4356                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4357                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4358                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4359                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4360                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4361                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4362                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4363                 CHECKCGERROR
4364         }
4365
4366         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4367                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4368         else
4369                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4370
4371         // free the strings
4372         if (vertstring)
4373                 Mem_Free(vertstring);
4374         if (geomstring)
4375                 Mem_Free(geomstring);
4376         if (fragstring)
4377                 Mem_Free(fragstring);
4378         if (vertexstring)
4379                 Mem_Free(vertexstring);
4380         if (geometrystring)
4381                 Mem_Free(geometrystring);
4382         if (fragmentstring)
4383                 Mem_Free(fragmentstring);
4384 }
4385
4386 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4387 {
4388         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4389         CHECKGLERROR
4390         CHECKCGERROR
4391         if (r_cg_permutation != perm)
4392         {
4393                 r_cg_permutation = perm;
4394                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4395                 {
4396                         if (!r_cg_permutation->compiled)
4397                                 R_CG_CompilePermutation(perm, mode, permutation);
4398                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4399                         {
4400                                 // remove features until we find a valid permutation
4401                                 int i;
4402                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4403                                 {
4404                                         // reduce i more quickly whenever it would not remove any bits
4405                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4406                                         if (!(permutation & j))
4407                                                 continue;
4408                                         permutation -= j;
4409                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4410                                         if (!r_cg_permutation->compiled)
4411                                                 R_CG_CompilePermutation(perm, mode, permutation);
4412                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4413                                                 break;
4414                                 }
4415                                 if (i >= SHADERPERMUTATION_COUNT)
4416                                 {
4417                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4418                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4419                                         return; // no bit left to clear, entire mode is broken
4420                                 }
4421                         }
4422                 }
4423                 CHECKGLERROR
4424                 CHECKCGERROR
4425                 if (r_cg_permutation->vprogram)
4426                 {
4427                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4428                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4429                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4430                 }
4431                 else
4432                 {
4433                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4434                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4435                 }
4436                 if (r_cg_permutation->fprogram)
4437                 {
4438                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4439                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4440                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4441                 }
4442                 else
4443                 {
4444                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4445                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4446                 }
4447         }
4448         CHECKCGERROR
4449         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4450         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4451         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4452 }
4453
4454 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4455 {
4456         cgGLSetTextureParameter(param, R_GetTexture(tex));
4457         cgGLEnableTextureParameter(param);
4458 }
4459 #endif
4460
4461 #ifdef SUPPORTD3D
4462
4463 #ifdef SUPPORTD3D
4464 #include <d3d9.h>
4465 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4466 extern D3DCAPS9 vid_d3d9caps;
4467 #endif
4468
4469 struct r_hlsl_permutation_s;
4470 typedef struct r_hlsl_permutation_s
4471 {
4472         /// hash lookup data
4473         struct r_hlsl_permutation_s *hashnext;
4474         unsigned int mode;
4475         unsigned int permutation;
4476
4477         /// indicates if we have tried compiling this permutation already
4478         qboolean compiled;
4479         /// NULL if compilation failed
4480         IDirect3DVertexShader9 *vertexshader;
4481         IDirect3DPixelShader9 *pixelshader;
4482 }
4483 r_hlsl_permutation_t;
4484
4485 typedef enum D3DVSREGISTER_e
4486 {
4487         D3DVSREGISTER_TexMatrix = 0, // float4x4
4488         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4489         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4490         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4491         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4492         D3DVSREGISTER_ModelToLight = 20, // float4x4
4493         D3DVSREGISTER_EyePosition = 24,
4494         D3DVSREGISTER_FogPlane = 25,
4495         D3DVSREGISTER_LightDir = 26,
4496         D3DVSREGISTER_LightPosition = 27,
4497 }
4498 D3DVSREGISTER_t;
4499
4500 typedef enum D3DPSREGISTER_e
4501 {
4502         D3DPSREGISTER_Alpha = 0,
4503         D3DPSREGISTER_BloomBlur_Parameters = 1,
4504         D3DPSREGISTER_ClientTime = 2,
4505         D3DPSREGISTER_Color_Ambient = 3,
4506         D3DPSREGISTER_Color_Diffuse = 4,
4507         D3DPSREGISTER_Color_Specular = 5,
4508         D3DPSREGISTER_Color_Glow = 6,
4509         D3DPSREGISTER_Color_Pants = 7,
4510         D3DPSREGISTER_Color_Shirt = 8,
4511         D3DPSREGISTER_DeferredColor_Ambient = 9,
4512         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4513         D3DPSREGISTER_DeferredColor_Specular = 11,
4514         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4515         D3DPSREGISTER_DeferredMod_Specular = 13,
4516         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4517         D3DPSREGISTER_EyePosition = 15, // unused
4518         D3DPSREGISTER_FogColor = 16,
4519         D3DPSREGISTER_FogHeightFade = 17,
4520         D3DPSREGISTER_FogPlane = 18,
4521         D3DPSREGISTER_FogPlaneViewDist = 19,
4522         D3DPSREGISTER_FogRangeRecip = 20,
4523         D3DPSREGISTER_LightColor = 21,
4524         D3DPSREGISTER_LightDir = 22, // unused
4525         D3DPSREGISTER_LightPosition = 23,
4526         D3DPSREGISTER_OffsetMapping_Scale = 24,
4527         D3DPSREGISTER_PixelSize = 25,
4528         D3DPSREGISTER_ReflectColor = 26,
4529         D3DPSREGISTER_ReflectFactor = 27,
4530         D3DPSREGISTER_ReflectOffset = 28,
4531         D3DPSREGISTER_RefractColor = 29,
4532         D3DPSREGISTER_Saturation = 30,
4533         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4534         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4535         D3DPSREGISTER_ScreenToDepth = 33,
4536         D3DPSREGISTER_ShadowMap_Parameters = 34,
4537         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4538         D3DPSREGISTER_SpecularPower = 36,
4539         D3DPSREGISTER_UserVec1 = 37,
4540         D3DPSREGISTER_UserVec2 = 38,
4541         D3DPSREGISTER_UserVec3 = 39,
4542         D3DPSREGISTER_UserVec4 = 40,
4543         D3DPSREGISTER_ViewTintColor = 41,
4544         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4545         D3DPSREGISTER_BloomColorSubtract = 43,
4546         D3DPSREGISTER_ViewToLight = 44, // float4x4
4547         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4548         D3DPSREGISTER_NormalmapScrollBlend = 52,
4549         // next at 53
4550 }
4551 D3DPSREGISTER_t;
4552
4553 /// information about each possible shader permutation
4554 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4555 /// currently selected permutation
4556 r_hlsl_permutation_t *r_hlsl_permutation;
4557 /// storage for permutations linked in the hash table
4558 memexpandablearray_t r_hlsl_permutationarray;
4559
4560 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4561 {
4562         //unsigned int hashdepth = 0;
4563         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4564         r_hlsl_permutation_t *p;
4565         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4566         {
4567                 if (p->mode == mode && p->permutation == permutation)
4568                 {
4569                         //if (hashdepth > 10)
4570                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4571                         return p;
4572                 }
4573                 //hashdepth++;
4574         }
4575         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4576         p->mode = mode;
4577         p->permutation = permutation;
4578         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4579         r_hlsl_permutationhash[mode][hashindex] = p;
4580         //if (hashdepth > 10)
4581         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4582         return p;
4583 }
4584
4585 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4586 {
4587         char *shaderstring;
4588         if (!filename || !filename[0])
4589                 return NULL;
4590         if (!strcmp(filename, "hlsl/default.hlsl"))
4591         {
4592                 if (!hlslshaderstring)
4593                 {
4594                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4595                         if (hlslshaderstring)
4596                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4597                         else
4598                                 hlslshaderstring = (char *)builtincgshaderstring;
4599                 }
4600                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4601                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4602                 return shaderstring;
4603         }
4604         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4605         if (shaderstring)
4606         {
4607                 if (printfromdisknotice)
4608                         Con_DPrintf("from disk %s... ", filename);
4609                 return shaderstring;
4610         }
4611         return shaderstring;
4612 }
4613
4614 #include <d3dx9.h>
4615 //#include <d3dx9shader.h>
4616 //#include <d3dx9mesh.h>
4617
4618 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4619 {
4620         DWORD *vsbin = NULL;
4621         DWORD *psbin = NULL;
4622         fs_offset_t vsbinsize;
4623         fs_offset_t psbinsize;
4624 //      IDirect3DVertexShader9 *vs = NULL;
4625 //      IDirect3DPixelShader9 *ps = NULL;
4626         ID3DXBuffer *vslog = NULL;
4627         ID3DXBuffer *vsbuffer = NULL;
4628         ID3DXConstantTable *vsconstanttable = NULL;
4629         ID3DXBuffer *pslog = NULL;
4630         ID3DXBuffer *psbuffer = NULL;
4631         ID3DXConstantTable *psconstanttable = NULL;
4632         int vsresult = 0;
4633         int psresult = 0;
4634         char temp[MAX_INPUTLINE];
4635         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4636         qboolean debugshader = gl_paranoid.integer != 0;
4637         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4638         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4639         if (!debugshader)
4640         {
4641                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4642                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4643         }
4644         if ((!vsbin && vertstring) || (!psbin && fragstring))
4645         {
4646                 const char* dllnames_d3dx9 [] =
4647                 {
4648                         "d3dx9_43.dll",
4649                         "d3dx9_42.dll",
4650                         "d3dx9_41.dll",
4651                         "d3dx9_40.dll",
4652                         "d3dx9_39.dll",
4653                         "d3dx9_38.dll",
4654                         "d3dx9_37.dll",
4655                         "d3dx9_36.dll",
4656                         "d3dx9_35.dll",
4657                         "d3dx9_34.dll",
4658                         "d3dx9_33.dll",
4659                         "d3dx9_32.dll",
4660                         "d3dx9_31.dll",
4661                         "d3dx9_30.dll",
4662                         "d3dx9_29.dll",
4663                         "d3dx9_28.dll",
4664                         "d3dx9_27.dll",
4665                         "d3dx9_26.dll",
4666                         "d3dx9_25.dll",
4667                         "d3dx9_24.dll",
4668                         NULL
4669                 };
4670                 dllhandle_t d3dx9_dll = NULL;
4671                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4672                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4673                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4674                 dllfunction_t d3dx9_dllfuncs[] =
4675                 {
4676                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4677                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4678                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4679                         {NULL, NULL}
4680                 };
4681                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4682                 {
4683                         DWORD shaderflags = 0;
4684                         if (debugshader)
4685                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4686                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4687                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4688                         if (vertstring && vertstring[0])
4689                         {
4690                                 if (debugshader)
4691                                 {
4692 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4693 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4694                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4695                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4696                                 }
4697                                 else
4698                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4699                                 if (vsbuffer)
4700                                 {
4701                                         vsbinsize = vsbuffer->GetBufferSize();
4702                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4703                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4704                                         vsbuffer->Release();
4705                                 }
4706                                 if (vslog)
4707                                 {
4708                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4709                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4710                                         vslog->Release();
4711                                 }
4712                         }
4713                         if (fragstring && fragstring[0])
4714                         {
4715                                 if (debugshader)
4716                                 {
4717 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4718 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4719                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4720                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4721                                 }
4722                                 else
4723                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4724                                 if (psbuffer)
4725                                 {
4726                                         psbinsize = psbuffer->GetBufferSize();
4727                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4728                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4729                                         psbuffer->Release();
4730                                 }
4731                                 if (pslog)
4732                                 {
4733                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4734                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4735                                         pslog->Release();
4736                                 }
4737                         }
4738                         Sys_UnloadLibrary(&d3dx9_dll);
4739                 }
4740                 else
4741                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4742         }
4743         if (vsbin && psbin)
4744         {
4745                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4746                 if (FAILED(vsresult))
4747                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4748                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4749                 if (FAILED(psresult))
4750                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4751         }
4752         // free the shader data
4753         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4754         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4755 }
4756
4757 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4758 {
4759         int i;
4760         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4761         int vertstring_length = 0;
4762         int geomstring_length = 0;
4763         int fragstring_length = 0;
4764         char *t;
4765         char *vertexstring, *geometrystring, *fragmentstring;
4766         char *vertstring, *geomstring, *fragstring;
4767         char permutationname[256];
4768         char cachename[256];
4769         int vertstrings_count = 0;
4770         int geomstrings_count = 0;
4771         int fragstrings_count = 0;
4772         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4773         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4774         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4775
4776         if (p->compiled)
4777                 return;
4778         p->compiled = true;
4779         p->vertexshader = NULL;
4780         p->pixelshader = NULL;
4781
4782         permutationname[0] = 0;
4783         cachename[0] = 0;
4784         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4785         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4786         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4787
4788         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4789         strlcat(cachename, "hlsl/", sizeof(cachename));
4790
4791         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4792         vertstrings_count = 0;
4793         geomstrings_count = 0;
4794         fragstrings_count = 0;
4795         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4796         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4797         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4798
4799         // the first pretext is which type of shader to compile as
4800         // (later these will all be bound together as a program object)
4801         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4802         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4803         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4804
4805         // the second pretext is the mode (for example a light source)
4806         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4807         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4808         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4809         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4810         strlcat(cachename, modeinfo->name, sizeof(cachename));
4811
4812         // now add all the permutation pretexts
4813         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4814         {
4815                 if (permutation & (1<<i))
4816                 {
4817                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4818                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4819                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4820                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4821                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4822                 }
4823                 else
4824                 {
4825                         // keep line numbers correct
4826                         vertstrings_list[vertstrings_count++] = "\n";
4827                         geomstrings_list[geomstrings_count++] = "\n";
4828                         fragstrings_list[fragstrings_count++] = "\n";
4829                 }
4830         }
4831
4832         // add static parms
4833         R_CompileShader_AddStaticParms(mode, permutation);
4834         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4835         vertstrings_count += shaderstaticparms_count;
4836         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4837         geomstrings_count += shaderstaticparms_count;
4838         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4839         fragstrings_count += shaderstaticparms_count;
4840
4841         // replace spaces in the cachename with _ characters
4842         for (i = 0;cachename[i];i++)
4843                 if (cachename[i] == ' ')
4844                         cachename[i] = '_';
4845
4846         // now append the shader text itself
4847         vertstrings_list[vertstrings_count++] = vertexstring;
4848         geomstrings_list[geomstrings_count++] = geometrystring;
4849         fragstrings_list[fragstrings_count++] = fragmentstring;
4850
4851         // if any sources were NULL, clear the respective list
4852         if (!vertexstring)
4853                 vertstrings_count = 0;
4854         if (!geometrystring)
4855                 geomstrings_count = 0;
4856         if (!fragmentstring)
4857                 fragstrings_count = 0;
4858
4859         vertstring_length = 0;
4860         for (i = 0;i < vertstrings_count;i++)
4861                 vertstring_length += strlen(vertstrings_list[i]);
4862         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4863         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4864                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4865
4866         geomstring_length = 0;
4867         for (i = 0;i < geomstrings_count;i++)
4868                 geomstring_length += strlen(geomstrings_list[i]);
4869         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4870         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4871                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4872
4873         fragstring_length = 0;
4874         for (i = 0;i < fragstrings_count;i++)
4875                 fragstring_length += strlen(fragstrings_list[i]);
4876         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4877         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4878                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4879
4880         // try to load the cached shader, or generate one
4881         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4882
4883         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4884                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4885         else
4886                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4887
4888         // free the strings
4889         if (vertstring)
4890                 Mem_Free(vertstring);
4891         if (geomstring)
4892                 Mem_Free(geomstring);
4893         if (fragstring)
4894                 Mem_Free(fragstring);
4895         if (vertexstring)
4896                 Mem_Free(vertexstring);
4897         if (geometrystring)
4898                 Mem_Free(geometrystring);
4899         if (fragmentstring)
4900                 Mem_Free(fragmentstring);
4901 }
4902
4903 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4904 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4905 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);}
4906 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);}
4907 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);}
4908 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);}
4909
4910 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4911 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4912 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);}
4913 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);}
4914 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);}
4915 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);}
4916
4917 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4918 {
4919         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4920         if (r_hlsl_permutation != perm)
4921         {
4922                 r_hlsl_permutation = perm;
4923                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4924                 {
4925                         if (!r_hlsl_permutation->compiled)
4926                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4927                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4928                         {
4929                                 // remove features until we find a valid permutation
4930                                 int i;
4931                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4932                                 {
4933                                         // reduce i more quickly whenever it would not remove any bits
4934                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4935                                         if (!(permutation & j))
4936                                                 continue;
4937                                         permutation -= j;
4938                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4939                                         if (!r_hlsl_permutation->compiled)
4940                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4941                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4942                                                 break;
4943                                 }
4944                                 if (i >= SHADERPERMUTATION_COUNT)
4945                                 {
4946                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4947                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4948                                         return; // no bit left to clear, entire mode is broken
4949                                 }
4950                         }
4951                 }
4952                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4953                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4954         }
4955         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4956         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4957         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4958 }
4959 #endif
4960
4961 void R_GLSL_Restart_f(void)
4962 {
4963         unsigned int i, limit;
4964         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4965                 Mem_Free(glslshaderstring);
4966         glslshaderstring = NULL;
4967         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4968                 Mem_Free(cgshaderstring);
4969         cgshaderstring = NULL;
4970         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4971                 Mem_Free(hlslshaderstring);
4972         hlslshaderstring = NULL;
4973         switch(vid.renderpath)
4974         {
4975         case RENDERPATH_D3D9:
4976 #ifdef SUPPORTD3D
4977                 {
4978                         r_hlsl_permutation_t *p;
4979                         r_hlsl_permutation = NULL;
4980 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4981 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4982 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4983 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4984                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4985                         for (i = 0;i < limit;i++)
4986                         {
4987                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4988                                 {
4989                                         if (p->vertexshader)
4990                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4991                                         if (p->pixelshader)
4992                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4993                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4994                                 }
4995                         }
4996                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4997                 }
4998 #endif
4999                 break;
5000         case RENDERPATH_D3D10:
5001                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5002                 break;
5003         case RENDERPATH_D3D11:
5004                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5005                 break;
5006         case RENDERPATH_GL20:
5007                 {
5008                         r_glsl_permutation_t *p;
5009                         r_glsl_permutation = NULL;
5010                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5011                         for (i = 0;i < limit;i++)
5012                         {
5013                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5014                                 {
5015                                         GL_Backend_FreeProgram(p->program);
5016                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5017                                 }
5018                         }
5019                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5020                 }
5021                 break;
5022         case RENDERPATH_CGGL:
5023 #ifdef SUPPORTCG
5024                 {
5025                         r_cg_permutation_t *p;
5026                         r_cg_permutation = NULL;
5027                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5028                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5029                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5030                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5031                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5032                         for (i = 0;i < limit;i++)
5033                         {
5034                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5035                                 {
5036                                         if (p->vprogram)
5037                                                 cgDestroyProgram(p->vprogram);
5038                                         if (p->fprogram)
5039                                                 cgDestroyProgram(p->fprogram);
5040                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5041                                 }
5042                         }
5043                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5044                 }
5045 #endif
5046                 break;
5047         case RENDERPATH_GL13:
5048         case RENDERPATH_GL11:
5049                 break;
5050         }
5051 }
5052
5053 void R_GLSL_DumpShader_f(void)
5054 {
5055         int i;
5056         qfile_t *file;
5057
5058         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5059         if (file)
5060         {
5061                 FS_Print(file, "/* The engine may define the following macros:\n");
5062                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5063                 for (i = 0;i < SHADERMODE_COUNT;i++)
5064                         FS_Print(file, glslshadermodeinfo[i].pretext);
5065                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5066                         FS_Print(file, shaderpermutationinfo[i].pretext);
5067                 FS_Print(file, "*/\n");
5068                 FS_Print(file, builtinshaderstring);
5069                 FS_Close(file);
5070                 Con_Printf("glsl/default.glsl written\n");
5071         }
5072         else
5073                 Con_Printf("failed to write to glsl/default.glsl\n");
5074
5075 #ifdef SUPPORTCG
5076         file = FS_OpenRealFile("cg/default.cg", "w", false);
5077         if (file)
5078         {
5079                 FS_Print(file, "/* The engine may define the following macros:\n");
5080                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5081                 for (i = 0;i < SHADERMODE_COUNT;i++)
5082                         FS_Print(file, cgshadermodeinfo[i].pretext);
5083                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5084                         FS_Print(file, shaderpermutationinfo[i].pretext);
5085                 FS_Print(file, "*/\n");
5086                 FS_Print(file, builtincgshaderstring);
5087                 FS_Close(file);
5088                 Con_Printf("cg/default.cg written\n");
5089         }
5090         else
5091                 Con_Printf("failed to write to cg/default.cg\n");
5092 #endif
5093
5094 #ifdef SUPPORTD3D
5095         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5096         if (file)
5097         {
5098                 FS_Print(file, "/* The engine may define the following macros:\n");
5099                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5100                 for (i = 0;i < SHADERMODE_COUNT;i++)
5101                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5102                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5103                         FS_Print(file, shaderpermutationinfo[i].pretext);
5104                 FS_Print(file, "*/\n");
5105                 FS_Print(file, builtincgshaderstring);
5106                 FS_Close(file);
5107                 Con_Printf("hlsl/default.hlsl written\n");
5108         }
5109         else
5110                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5111 #endif
5112 }
5113
5114 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5115 {
5116         if (!second)
5117                 texturemode = GL_MODULATE;
5118         switch (vid.renderpath)
5119         {
5120         case RENDERPATH_D3D9:
5121 #ifdef SUPPORTD3D
5122                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5123                 R_Mesh_TexBind(GL20TU_FIRST , first );
5124                 R_Mesh_TexBind(GL20TU_SECOND, second);
5125 #endif
5126                 break;
5127         case RENDERPATH_D3D10:
5128                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5129                 break;
5130         case RENDERPATH_D3D11:
5131                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5132                 break;
5133         case RENDERPATH_GL20:
5134                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5135                 R_Mesh_TexBind(GL20TU_FIRST , first );
5136                 R_Mesh_TexBind(GL20TU_SECOND, second);
5137                 break;
5138         case RENDERPATH_CGGL:
5139 #ifdef SUPPORTCG
5140                 CHECKCGERROR
5141                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5142                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5143                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5144 #endif
5145                 break;
5146         case RENDERPATH_GL13:
5147                 R_Mesh_TexBind(0, first );
5148                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5149                 R_Mesh_TexBind(1, second);
5150                 if (second)
5151                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5152                 break;
5153         case RENDERPATH_GL11:
5154                 R_Mesh_TexBind(0, first );
5155                 break;
5156         }
5157 }
5158
5159 void R_SetupShader_DepthOrShadow(void)
5160 {
5161         switch (vid.renderpath)
5162         {
5163         case RENDERPATH_D3D9:
5164 #ifdef SUPPORTD3D
5165                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5166 #endif
5167                 break;
5168         case RENDERPATH_D3D10:
5169                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5170                 break;
5171         case RENDERPATH_D3D11:
5172                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5173                 break;
5174         case RENDERPATH_GL20:
5175                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5176                 break;
5177         case RENDERPATH_CGGL:
5178 #ifdef SUPPORTCG
5179                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5180 #endif
5181                 break;
5182         case RENDERPATH_GL13:
5183                 R_Mesh_TexBind(0, 0);
5184                 R_Mesh_TexBind(1, 0);
5185                 break;
5186         case RENDERPATH_GL11:
5187                 R_Mesh_TexBind(0, 0);
5188                 break;
5189         }
5190 }
5191
5192 void R_SetupShader_ShowDepth(void)
5193 {
5194         switch (vid.renderpath)
5195         {
5196         case RENDERPATH_D3D9:
5197 #ifdef SUPPORTHLSL
5198                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5199 #endif
5200                 break;
5201         case RENDERPATH_D3D10:
5202                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5203                 break;
5204         case RENDERPATH_D3D11:
5205                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5206                 break;
5207         case RENDERPATH_GL20:
5208                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5209                 break;
5210         case RENDERPATH_CGGL:
5211 #ifdef SUPPORTCG
5212                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5213 #endif
5214                 break;
5215         case RENDERPATH_GL13:
5216                 break;
5217         case RENDERPATH_GL11:
5218                 break;
5219         }
5220 }
5221
5222 extern qboolean r_shadow_usingdeferredprepass;
5223 extern cvar_t r_shadow_deferred_8bitrange;
5224 extern rtexture_t *r_shadow_attenuationgradienttexture;
5225 extern rtexture_t *r_shadow_attenuation2dtexture;
5226 extern rtexture_t *r_shadow_attenuation3dtexture;
5227 extern qboolean r_shadow_usingshadowmap2d;
5228 extern qboolean r_shadow_usingshadowmaportho;
5229 extern float r_shadow_shadowmap_texturescale[2];
5230 extern float r_shadow_shadowmap_parameters[4];
5231 extern qboolean r_shadow_shadowmapvsdct;
5232 extern qboolean r_shadow_shadowmapsampler;
5233 extern int r_shadow_shadowmappcf;
5234 extern rtexture_t *r_shadow_shadowmap2dtexture;
5235 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5236 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5237 extern matrix4x4_t r_shadow_shadowmapmatrix;
5238 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5239 extern int r_shadow_prepass_width;
5240 extern int r_shadow_prepass_height;
5241 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5242 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5243 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5244 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5245 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5246 extern cvar_t gl_mesh_separatearrays;
5247 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5248 {
5249         // a blendfunc allows colormod if:
5250         // a) it can never keep the destination pixel invariant, or
5251         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5252         // this is to prevent unintended side effects from colormod
5253
5254         // in formulas:
5255         // IF there is a (s, sa) for which for all (d, da),
5256         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5257         // THEN, for this (s, sa) and all (colormod, d, da):
5258         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5259         // OBVIOUSLY, this means that
5260         //   s*colormod * src(s*colormod, d, sa, da) = 0
5261         //   dst(s*colormod, d, sa, da)              = 1
5262
5263         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5264
5265         // main condition to leave dst color invariant:
5266         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5267         //   src == GL_ZERO:
5268         //     s * 0 + d * dst(s, d, sa, da) == d
5269         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5270         //       => colormod is a problem for GL_SRC_COLOR only
5271         //   src == GL_ONE:
5272         //     s + d * dst(s, d, sa, da) == d
5273         //       => s == 0
5274         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5275         //       => colormod is never problematic for these
5276         //   src == GL_SRC_COLOR:
5277         //     s*s + d * dst(s, d, sa, da) == d
5278         //       => s == 0
5279         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5280         //       => colormod is never problematic for these
5281         //   src == GL_ONE_MINUS_SRC_COLOR:
5282         //     s*(1-s) + d * dst(s, d, sa, da) == d
5283         //       => s == 0 or s == 1
5284         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5285         //       => colormod is a problem for GL_SRC_COLOR only
5286         //   src == GL_DST_COLOR
5287         //     s*d + d * dst(s, d, sa, da) == d
5288         //       => s == 1
5289         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290         //       => colormod is always a problem
5291         //     or
5292         //       => s == 0
5293         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5294         //       => colormod is never problematic for these
5295         //       => BUT, we do not know s! We must assume it is problematic
5296         //       then... except in GL_ONE case, where we know all invariant
5297         //       cases are fine
5298         //   src == GL_ONE_MINUS_DST_COLOR
5299         //     s*(1-d) + d * dst(s, d, sa, da) == d
5300         //       => s == 0 (1-d is impossible to handle for our desired result)
5301         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is never problematic for these
5303         //   src == GL_SRC_ALPHA
5304         //     s*sa + d * dst(s, d, sa, da) == d
5305         //       => s == 0, or sa == 0
5306         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod breaks in the case GL_SRC_COLOR only
5308         //   src == GL_ONE_MINUS_SRC_ALPHA
5309         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5310         //       => s == 0, or sa == 1
5311         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312         //       => colormod breaks in the case GL_SRC_COLOR only
5313         //   src == GL_DST_ALPHA
5314         //     s*da + d * dst(s, d, sa, da) == d
5315         //       => s == 0
5316         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5317         //       => colormod is never problematic for these
5318
5319         switch(src)
5320         {
5321                 case GL_ZERO:
5322                 case GL_ONE_MINUS_SRC_COLOR:
5323                 case GL_SRC_ALPHA:
5324                 case GL_ONE_MINUS_SRC_ALPHA:
5325                         if(dst == GL_SRC_COLOR)
5326                                 return false;
5327                         return true;
5328                 case GL_ONE:
5329                 case GL_SRC_COLOR:
5330                 case GL_ONE_MINUS_DST_COLOR:
5331                 case GL_DST_ALPHA:
5332                 case GL_ONE_MINUS_DST_ALPHA:
5333                         return true;
5334                 case GL_DST_COLOR:
5335                         if(dst == GL_ONE)
5336                                 return true;
5337                         return false;
5338                 default:
5339                         return false;
5340         }
5341 }
5342 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)
5343 {
5344         // select a permutation of the lighting shader appropriate to this
5345         // combination of texture, entity, light source, and fogging, only use the
5346         // minimum features necessary to avoid wasting rendering time in the
5347         // fragment shader on features that are not being used
5348         unsigned int permutation = 0;
5349         unsigned int mode = 0;
5350         qboolean allow_colormod;
5351         static float dummy_colormod[3] = {1, 1, 1};
5352         float *colormod = rsurface.colormod;
5353         float m16f[16];
5354         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5355         if (rsurfacepass == RSURFPASS_BACKGROUND)
5356         {
5357                 // distorted background
5358                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5359                 {
5360                         mode = SHADERMODE_WATER;
5361                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5362                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5363                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5364                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5365                 }
5366                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5367                 {
5368                         mode = SHADERMODE_REFRACTION;
5369                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5370                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5371                 }
5372                 else
5373                 {
5374                         mode = SHADERMODE_GENERIC;
5375                         permutation |= SHADERPERMUTATION_DIFFUSE;
5376                         GL_BlendFunc(GL_ONE, GL_ZERO);
5377                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5378                 }
5379                 GL_AlphaTest(false);
5380         }
5381         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5382         {
5383                 if (r_glsl_offsetmapping.integer)
5384                 {
5385                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5386                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5387                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5388                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5389                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5390                         {
5391                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5392                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5393                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5394                         }
5395                 }
5396                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5397                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5399                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5400                 // normalmap (deferred prepass), may use alpha test on diffuse
5401                 mode = SHADERMODE_DEFERREDGEOMETRY;
5402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404                 GL_AlphaTest(false);
5405                 GL_BlendFunc(GL_ONE, GL_ZERO);
5406                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5407         }
5408         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5409         {
5410                 if (r_glsl_offsetmapping.integer)
5411                 {
5412                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5413                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5415                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5417                         {
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5419                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5420                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5421                         }
5422                 }
5423                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5425                 // light source
5426                 mode = SHADERMODE_LIGHTSOURCE;
5427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5429                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5430                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5431                 if (diffusescale > 0)
5432                         permutation |= SHADERPERMUTATION_DIFFUSE;
5433                 if (specularscale > 0)
5434                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5435                 if (r_refdef.fogenabled)
5436                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5437                 if (rsurface.texture->colormapping)
5438                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5439                 if (r_shadow_usingshadowmap2d)
5440                 {
5441                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5442                         if(r_shadow_shadowmapvsdct)
5443                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5444
5445                         if (r_shadow_shadowmapsampler)
5446                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5447                         if (r_shadow_shadowmappcf > 1)
5448                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5449                         else if (r_shadow_shadowmappcf)
5450                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5451                 }
5452                 if (rsurface.texture->reflectmasktexture)
5453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5454                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5455                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5456                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5457         }
5458         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5459         {
5460                 if (r_glsl_offsetmapping.integer)
5461                 {
5462                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5467                         {
5468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5470                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5471                         }
5472                 }
5473                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5475                 // unshaded geometry (fullbright or ambient model lighting)
5476                 mode = SHADERMODE_FLATCOLOR;
5477                 ambientscale = diffusescale = specularscale = 0;
5478                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5479                         permutation |= SHADERPERMUTATION_GLOW;
5480                 if (r_refdef.fogenabled)
5481                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5482                 if (rsurface.texture->colormapping)
5483                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5484                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5485                 {
5486                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5487                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5488
5489                         if (r_shadow_shadowmapsampler)
5490                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5491                         if (r_shadow_shadowmappcf > 1)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5493                         else if (r_shadow_shadowmappcf)
5494                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5495                 }
5496                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5497                         permutation |= SHADERPERMUTATION_REFLECTION;
5498                 if (rsurface.texture->reflectmasktexture)
5499                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5500                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5501                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5502                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5503         }
5504         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5505         {
5506                 if (r_glsl_offsetmapping.integer)
5507                 {
5508                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5509                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5510                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5511                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5512                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5513                         {
5514                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5515                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5516                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5517                         }
5518                 }
5519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5520                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5521                 // directional model lighting
5522                 mode = SHADERMODE_LIGHTDIRECTION;
5523                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5524                         permutation |= SHADERPERMUTATION_GLOW;
5525                 permutation |= SHADERPERMUTATION_DIFFUSE;
5526                 if (specularscale > 0)
5527                         permutation |= SHADERPERMUTATION_SPECULAR;
5528                 if (r_refdef.fogenabled)
5529                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5530                 if (rsurface.texture->colormapping)
5531                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5532                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5533                 {
5534                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5535                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5536
5537                         if (r_shadow_shadowmapsampler)
5538                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5539                         if (r_shadow_shadowmappcf > 1)
5540                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5541                         else if (r_shadow_shadowmappcf)
5542                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5543                 }
5544                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5545                         permutation |= SHADERPERMUTATION_REFLECTION;
5546                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5547                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5548                 if (rsurface.texture->reflectmasktexture)
5549                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5550                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5551                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5552                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5553         }
5554         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5555         {
5556                 if (r_glsl_offsetmapping.integer)
5557                 {
5558                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5559                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5560                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5561                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5562                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5563                         {
5564                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5565                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5566                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5567                         }
5568                 }
5569                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5570                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5571                 // ambient model lighting
5572                 mode = SHADERMODE_LIGHTDIRECTION;
5573                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5574                         permutation |= SHADERPERMUTATION_GLOW;
5575                 if (r_refdef.fogenabled)
5576                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5577                 if (rsurface.texture->colormapping)
5578                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5579                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5580                 {
5581                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5582                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5583
5584                         if (r_shadow_shadowmapsampler)
5585                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5586                         if (r_shadow_shadowmappcf > 1)
5587                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5588                         else if (r_shadow_shadowmappcf)
5589                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5590                 }
5591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5592                         permutation |= SHADERPERMUTATION_REFLECTION;
5593                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5594                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5595                 if (rsurface.texture->reflectmasktexture)
5596                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5597                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5598                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5599                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5600         }
5601         else
5602         {
5603                 if (r_glsl_offsetmapping.integer)
5604                 {
5605                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5606                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5607                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5608                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5609                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5610                         {
5611                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5612                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5613                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5614                         }
5615                 }
5616                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5617                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5618                 // lightmapped wall
5619                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5620                         permutation |= SHADERPERMUTATION_GLOW;
5621                 if (r_refdef.fogenabled)
5622                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5623                 if (rsurface.texture->colormapping)
5624                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5625                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5626                 {
5627                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5628                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5629
5630                         if (r_shadow_shadowmapsampler)
5631                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5632                         if (r_shadow_shadowmappcf > 1)
5633                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5634                         else if (r_shadow_shadowmappcf)
5635                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5636                 }
5637                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5638                         permutation |= SHADERPERMUTATION_REFLECTION;
5639                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5640                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5641                 if (rsurface.texture->reflectmasktexture)
5642                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5643                 if (FAKELIGHT_ENABLED)
5644                 {
5645                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5646                         mode = SHADERMODE_FAKELIGHT;
5647                         permutation |= SHADERPERMUTATION_DIFFUSE;
5648                         if (specularscale > 0)
5649                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5650                 }
5651                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5652                 {
5653                         // deluxemapping (light direction texture)
5654                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5655                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5656                         else
5657                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5658                         permutation |= SHADERPERMUTATION_DIFFUSE;
5659                         if (specularscale > 0)
5660                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5661                 }
5662                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5663                 {
5664                         // fake deluxemapping (uniform light direction in tangentspace)
5665                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5666                         permutation |= SHADERPERMUTATION_DIFFUSE;
5667                         if (specularscale > 0)
5668                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5669                 }
5670                 else if (rsurface.uselightmaptexture)
5671                 {
5672                         // ordinary lightmapping (q1bsp, q3bsp)
5673                         mode = SHADERMODE_LIGHTMAP;
5674                 }
5675                 else
5676                 {
5677                         // ordinary vertex coloring (q3bsp)
5678                         mode = SHADERMODE_VERTEXCOLOR;
5679                 }
5680                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5681                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5682                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5683         }
5684         if(!allow_colormod)
5685                 colormod = dummy_colormod;
5686         switch(vid.renderpath)
5687         {
5688         case RENDERPATH_D3D9:
5689 #ifdef SUPPORTD3D
5690                 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);
5691                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5692                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5693                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5694                 if (mode == SHADERMODE_LIGHTSOURCE)
5695                 {
5696                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5697                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5698                 }
5699                 else
5700                 {
5701                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5702                         {
5703                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5704                         }
5705                 }
5706                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5707                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5708                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5709                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5710                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5711
5712                 if (mode == SHADERMODE_LIGHTSOURCE)
5713                 {
5714                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5715                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5716                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5717                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5718                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5719
5720                         // additive passes are only darkened by fog, not tinted
5721                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5722                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5723                 }
5724                 else
5725                 {
5726                         if (mode == SHADERMODE_FLATCOLOR)
5727                         {
5728                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5729                         }
5730                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5731                         {
5732                                 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]);
5733                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5734                                 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);
5735                                 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);
5736                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5737                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5738                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5739                         }
5740                         else
5741                         {
5742                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5743                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5744                                 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);
5745                                 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);
5746                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5747                         }
5748                         // additive passes are only darkened by fog, not tinted
5749                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5750                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5751                         else
5752                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5753                         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);
5754                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5755                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5756                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5757                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5758                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5759                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5760                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5761                         if (mode == SHADERMODE_WATER)
5762                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5763                 }
5764                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5765                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5766                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5767                 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));
5768                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5769                 if (rsurface.texture->pantstexture)
5770                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5771                 else
5772                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5773                 if (rsurface.texture->shirttexture)
5774                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5775                 else
5776                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5777                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5778                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5779                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5780                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5781                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5782                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5783                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5784
5785                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5786                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5787                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5788                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5789                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5790                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5791                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5792                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5793                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5794                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5795                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5796                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5797                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5798                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5799                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5800                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5801                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5802                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5803                 {
5804                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5805                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5806                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5807                 }
5808                 else
5809                 {
5810                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5811                 }
5812 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5813 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5814                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5815                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5816                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5817                 {
5818                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5819                         if (rsurface.rtlight)
5820                         {
5821                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5822                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5823                         }
5824                 }
5825 #endif
5826                 break;
5827         case RENDERPATH_D3D10:
5828                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5829                 break;
5830         case RENDERPATH_D3D11:
5831                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5832                 break;
5833         case RENDERPATH_GL20:
5834                 if (gl_mesh_separatearrays.integer)
5835                 {
5836                         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);
5837                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5838                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5839                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5840                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5841                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5842                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5843                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5844                 }
5845                 else
5846                 {
5847                         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);
5848                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5849                 }
5850                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5851                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5852                 if (mode == SHADERMODE_LIGHTSOURCE)
5853                 {
5854                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5855                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5856                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5857                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5858                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5859                         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);
5860         
5861                         // additive passes are only darkened by fog, not tinted
5862                         if (r_glsl_permutation->loc_FogColor >= 0)
5863                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5864                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5865                 }
5866                 else
5867                 {
5868                         if (mode == SHADERMODE_FLATCOLOR)
5869                         {
5870                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5871                         }
5872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5873                         {
5874                                 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) * 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]);
5875                                 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]);
5876                                 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);
5877                                 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);
5878                                 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);
5879                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5880                                 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]);
5881                         }
5882                         else
5883                         {
5884                                 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]);
5885                                 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]);
5886                                 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);
5887                                 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);
5888                                 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);
5889                         }
5890                         // additive passes are only darkened by fog, not tinted
5891                         if (r_glsl_permutation->loc_FogColor >= 0)
5892                         {
5893                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5894                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5895                                 else
5896                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5897                         }
5898                         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);
5899                         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]);
5900                         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]);
5901                         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]);
5902                         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]);
5903                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5904                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5905                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5906                         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]);
5907                 }
5908                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5909                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5910                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5911                 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]);
5912                 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]);
5913
5914                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5915                 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));
5916                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5917                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5918                 {
5919                         if (rsurface.texture->pantstexture)
5920                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5921                         else
5922                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5923                 }
5924                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5925                 {
5926                         if (rsurface.texture->shirttexture)
5927                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5928                         else
5929                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5930                 }
5931                 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]);
5932                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5933                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5934                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5935                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5936                 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]);
5937                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5938
5939         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5940         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5941         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5942                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5943                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5944                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5945                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5946                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5947                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5948                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5949                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5950                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5951                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5952                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5953                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5954                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5955                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5956                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5957                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5958                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5959                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5960                 {
5961                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5962                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5963                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5964                 }
5965                 else
5966                 {
5967                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5968                 }
5969 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5970 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5971                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5972                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5973                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5974                 {
5975                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5976                         if (rsurface.rtlight)
5977                         {
5978                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5979                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5980                         }
5981                 }
5982                 CHECKGLERROR
5983                 break;
5984         case RENDERPATH_CGGL:
5985 #ifdef SUPPORTCG
5986                 if (gl_mesh_separatearrays.integer)
5987                 {
5988                         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);
5989                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5990                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5991                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5992                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5993                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5994                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5995                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5996                 }
5997                 else
5998                 {
5999                         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);
6000                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6001                 }
6002                 R_SetupShader_SetPermutationCG(mode, permutation);
6003                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6004                 if (mode == SHADERMODE_LIGHTSOURCE)
6005                 {
6006                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6007                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6008                 }
6009                 else
6010                 {
6011                         if (mode == SHADERMODE_LIGHTDIRECTION)
6012                         {
6013                                 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
6014                         }
6015                 }
6016                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6017                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6018                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6019                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6020                 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
6021                 CHECKGLERROR
6022
6023                 if (mode == SHADERMODE_LIGHTSOURCE)
6024                 {
6025                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6026                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6027                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6028                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6029                         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
6030
6031                         // additive passes are only darkened by fog, not tinted
6032                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6033                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6034                 }
6035                 else
6036                 {
6037                         if (mode == SHADERMODE_FLATCOLOR)
6038                         {
6039                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6040                         }
6041                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6042                         {
6043                                 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
6044                                 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
6045                                 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
6046                                 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
6047                                 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
6048                                 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
6049                                 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
6050                         }
6051                         else
6052                         {
6053                                 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
6054                                 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
6055                                 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
6056                                 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
6057                                 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
6058                         }
6059                         // additive passes are only darkened by fog, not tinted
6060                         if (r_cg_permutation->fp_FogColor)
6061                         {
6062                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6063                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6064                                 else
6065                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6066                                 CHECKCGERROR
6067                         }
6068                         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
6069                         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
6070                         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
6071                         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
6072                         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
6073                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6074                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6075                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6076                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6077                 }
6078                 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
6079                 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
6080                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6081                 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
6082                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6083                 if (r_cg_permutation->fp_Color_Pants)
6084                 {
6085                         if (rsurface.texture->pantstexture)
6086                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6087                         else
6088                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6089                         CHECKCGERROR
6090                 }
6091                 if (r_cg_permutation->fp_Color_Shirt)
6092                 {
6093                         if (rsurface.texture->shirttexture)
6094                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6095                         else
6096                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6097                         CHECKCGERROR
6098                 }
6099                 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
6100                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6101                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6102                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6103                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6104                 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
6105                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6106
6107         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6108         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6109         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6110                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6111                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6112                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6113                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6114                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6115                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6116                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6117                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6118                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6119                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6120                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6121                 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
6122                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6123                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6124                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6125                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6126                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6127                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6128                 {
6129                         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
6130                         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
6131                         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
6132                 }
6133                 else
6134                 {
6135                         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
6136                 }
6137                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6139                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6140                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6141                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6142                 {
6143                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6144                         if (rsurface.rtlight)
6145                         {
6146                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6147                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6148                         }
6149                 }
6150
6151                 CHECKGLERROR
6152 #endif
6153                 break;
6154         case RENDERPATH_GL13:
6155         case RENDERPATH_GL11:
6156                 break;
6157         }
6158 }
6159
6160 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6161 {
6162         // select a permutation of the lighting shader appropriate to this
6163         // combination of texture, entity, light source, and fogging, only use the
6164         // minimum features necessary to avoid wasting rendering time in the
6165         // fragment shader on features that are not being used
6166         unsigned int permutation = 0;
6167         unsigned int mode = 0;
6168         const float *lightcolorbase = rtlight->currentcolor;
6169         float ambientscale = rtlight->ambientscale;
6170         float diffusescale = rtlight->diffusescale;
6171         float specularscale = rtlight->specularscale;
6172         // this is the location of the light in view space
6173         vec3_t viewlightorigin;
6174         // this transforms from view space (camera) to light space (cubemap)
6175         matrix4x4_t viewtolight;
6176         matrix4x4_t lighttoview;
6177         float viewtolight16f[16];
6178         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6179         // light source
6180         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6181         if (rtlight->currentcubemap != r_texture_whitecube)
6182                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6183         if (diffusescale > 0)
6184                 permutation |= SHADERPERMUTATION_DIFFUSE;
6185         if (specularscale > 0)
6186                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6187         if (r_shadow_usingshadowmap2d)
6188         {
6189                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6190                 if (r_shadow_shadowmapvsdct)
6191                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6192
6193                 if (r_shadow_shadowmapsampler)
6194                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6195                 if (r_shadow_shadowmappcf > 1)
6196                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6197                 else if (r_shadow_shadowmappcf)
6198                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6199         }
6200         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6201         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6202         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6203         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6204         switch(vid.renderpath)
6205         {
6206         case RENDERPATH_D3D9:
6207 #ifdef SUPPORTD3D
6208                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6209                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6210                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6211                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6212                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6213                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6214                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6215                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6216                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6217                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6218                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6219
6220                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6221                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6222                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6223                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6224                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6225                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6226 #endif
6227                 break;
6228         case RENDERPATH_D3D10:
6229                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6230                 break;
6231         case RENDERPATH_D3D11:
6232                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6233                 break;
6234         case RENDERPATH_GL20:
6235                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6236                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6237                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6238                 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);
6239                 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);
6240                 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);
6241                 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]);
6242                 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]);
6243                 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));
6244                 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]);
6245                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6246
6247                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6248                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6249                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6250                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6251                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6252                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6253                 break;
6254         case RENDERPATH_CGGL:
6255 #ifdef SUPPORTCG
6256                 R_SetupShader_SetPermutationCG(mode, permutation);
6257                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6258                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6259                 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
6260                 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
6261                 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
6262                 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
6263                 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
6264                 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
6265                 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
6266                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6267
6268                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6269                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6270                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6271                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6272                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6273                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6274 #endif
6275                 break;
6276         case RENDERPATH_GL13:
6277         case RENDERPATH_GL11:
6278                 break;
6279         }
6280 }
6281
6282 #define SKINFRAME_HASH 1024
6283
6284 typedef struct
6285 {
6286         int loadsequence; // incremented each level change
6287         memexpandablearray_t array;
6288         skinframe_t *hash[SKINFRAME_HASH];
6289 }
6290 r_skinframe_t;
6291 r_skinframe_t r_skinframe;
6292
6293 void R_SkinFrame_PrepareForPurge(void)
6294 {
6295         r_skinframe.loadsequence++;
6296         // wrap it without hitting zero
6297         if (r_skinframe.loadsequence >= 200)
6298                 r_skinframe.loadsequence = 1;
6299 }
6300
6301 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6302 {
6303         if (!skinframe)
6304                 return;
6305         // mark the skinframe as used for the purging code
6306         skinframe->loadsequence = r_skinframe.loadsequence;
6307 }
6308
6309 void R_SkinFrame_Purge(void)
6310 {
6311         int i;
6312         skinframe_t *s;
6313         for (i = 0;i < SKINFRAME_HASH;i++)
6314         {
6315                 for (s = r_skinframe.hash[i];s;s = s->next)
6316                 {
6317                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6318                         {
6319                                 if (s->merged == s->base)
6320                                         s->merged = NULL;
6321                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6322                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6323                                 R_PurgeTexture(s->merged);s->merged = NULL;
6324                                 R_PurgeTexture(s->base  );s->base   = NULL;
6325                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6326                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6327                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6328                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6329                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6330                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6331                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6332                                 s->loadsequence = 0;
6333                         }
6334                 }
6335         }
6336 }
6337
6338 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6339         skinframe_t *item;
6340         char basename[MAX_QPATH];
6341
6342         Image_StripImageExtension(name, basename, sizeof(basename));
6343
6344         if( last == NULL ) {
6345                 int hashindex;
6346                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6347                 item = r_skinframe.hash[hashindex];
6348         } else {
6349                 item = last->next;
6350         }
6351
6352         // linearly search through the hash bucket
6353         for( ; item ; item = item->next ) {
6354                 if( !strcmp( item->basename, basename ) ) {
6355                         return item;
6356                 }
6357         }
6358         return NULL;
6359 }
6360
6361 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6362 {
6363         skinframe_t *item;
6364         int hashindex;
6365         char basename[MAX_QPATH];
6366
6367         Image_StripImageExtension(name, basename, sizeof(basename));
6368
6369         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6370         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6371                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6372                         break;
6373
6374         if (!item) {
6375                 rtexture_t *dyntexture;
6376                 // check whether its a dynamic texture
6377                 dyntexture = CL_GetDynTexture( basename );
6378                 if (!add && !dyntexture)
6379                         return NULL;
6380                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6381                 memset(item, 0, sizeof(*item));
6382                 strlcpy(item->basename, basename, sizeof(item->basename));
6383                 item->base = dyntexture; // either NULL or dyntexture handle
6384                 item->textureflags = textureflags;
6385                 item->comparewidth = comparewidth;
6386                 item->compareheight = compareheight;
6387                 item->comparecrc = comparecrc;
6388                 item->next = r_skinframe.hash[hashindex];
6389                 r_skinframe.hash[hashindex] = item;
6390         }
6391         else if( item->base == NULL )
6392         {
6393                 rtexture_t *dyntexture;
6394                 // check whether its a dynamic texture
6395                 // 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]
6396                 dyntexture = CL_GetDynTexture( basename );
6397                 item->base = dyntexture; // either NULL or dyntexture handle
6398         }
6399
6400         R_SkinFrame_MarkUsed(item);
6401         return item;
6402 }
6403
6404 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6405         { \
6406                 unsigned long long avgcolor[5], wsum; \
6407                 int pix, comp, w; \
6408                 avgcolor[0] = 0; \
6409                 avgcolor[1] = 0; \
6410                 avgcolor[2] = 0; \
6411                 avgcolor[3] = 0; \
6412                 avgcolor[4] = 0; \
6413                 wsum = 0; \
6414                 for(pix = 0; pix < cnt; ++pix) \
6415                 { \
6416                         w = 0; \
6417                         for(comp = 0; comp < 3; ++comp) \
6418                                 w += getpixel; \
6419                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6420                         { \
6421                                 ++wsum; \
6422                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6423                                 w = getpixel; \
6424                                 for(comp = 0; comp < 3; ++comp) \
6425                                         avgcolor[comp] += getpixel * w; \
6426                                 avgcolor[3] += w; \
6427                         } \
6428                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6429                         avgcolor[4] += getpixel; \
6430                 } \
6431                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6432                         avgcolor[3] = 1; \
6433                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6434                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6435                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6436                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6437         }
6438
6439 extern cvar_t gl_picmip;
6440 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6441 {
6442         int j;
6443         unsigned char *pixels;
6444         unsigned char *bumppixels;
6445         unsigned char *basepixels = NULL;
6446         int basepixels_width = 0;
6447         int basepixels_height = 0;
6448         skinframe_t *skinframe;
6449         rtexture_t *ddsbase = NULL;
6450         qboolean ddshasalpha = false;
6451         float ddsavgcolor[4];
6452         char basename[MAX_QPATH];
6453         int miplevel = R_PicmipForFlags(textureflags);
6454         int savemiplevel = miplevel;
6455         int mymiplevel;
6456
6457         if (cls.state == ca_dedicated)
6458                 return NULL;
6459
6460         // return an existing skinframe if already loaded
6461         // if loading of the first image fails, don't make a new skinframe as it
6462         // would cause all future lookups of this to be missing
6463         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6464         if (skinframe && skinframe->base)
6465                 return skinframe;
6466
6467         Image_StripImageExtension(name, basename, sizeof(basename));
6468
6469         // check for DDS texture file first
6470         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6471         {
6472                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6473                 if (basepixels == NULL)
6474                         return NULL;
6475         }
6476
6477         // FIXME handle miplevel
6478
6479         if (developer_loading.integer)
6480                 Con_Printf("loading skin \"%s\"\n", name);
6481
6482         // we've got some pixels to store, so really allocate this new texture now
6483         if (!skinframe)
6484                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6485         skinframe->stain = NULL;
6486         skinframe->merged = NULL;
6487         skinframe->base = NULL;
6488         skinframe->pants = NULL;
6489         skinframe->shirt = NULL;
6490         skinframe->nmap = NULL;
6491         skinframe->gloss = NULL;
6492         skinframe->glow = NULL;
6493         skinframe->fog = NULL;
6494         skinframe->reflect = NULL;
6495         skinframe->hasalpha = false;
6496
6497         if (ddsbase)
6498         {
6499                 skinframe->base = ddsbase;
6500                 skinframe->hasalpha = ddshasalpha;
6501                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6502                 if (r_loadfog && skinframe->hasalpha)
6503                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6504                 //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]);
6505         }
6506         else
6507         {
6508                 basepixels_width = image_width;
6509                 basepixels_height = image_height;
6510                 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);
6511                 if (textureflags & TEXF_ALPHA)
6512                 {
6513                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6514                         {
6515                                 if (basepixels[j] < 255)
6516                                 {
6517                                         skinframe->hasalpha = true;
6518                                         break;
6519                                 }
6520                         }
6521                         if (r_loadfog && skinframe->hasalpha)
6522                         {
6523                                 // has transparent pixels
6524                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6525                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6526                                 {
6527                                         pixels[j+0] = 255;
6528                                         pixels[j+1] = 255;
6529                                         pixels[j+2] = 255;
6530                                         pixels[j+3] = basepixels[j+3];
6531                                 }
6532                                 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);
6533                                 Mem_Free(pixels);
6534                         }
6535                 }
6536                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6537                 //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]);
6538                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6539                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6540                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6541                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6542         }
6543
6544         if (r_loaddds)
6545         {
6546                 mymiplevel = savemiplevel;
6547                 if (r_loadnormalmap)
6548                         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);
6549                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6550                 if (r_loadgloss)
6551                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6552                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6553                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6554                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6555         }
6556
6557         // _norm is the name used by tenebrae and has been adopted as standard
6558         if (r_loadnormalmap && skinframe->nmap == NULL)
6559         {
6560                 mymiplevel = savemiplevel;
6561                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6562                 {
6563                         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);
6564                         Mem_Free(pixels);
6565                         pixels = NULL;
6566                 }
6567                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6568                 {
6569                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6570                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6571                         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);
6572                         Mem_Free(pixels);
6573                         Mem_Free(bumppixels);
6574                 }
6575                 else if (r_shadow_bumpscale_basetexture.value > 0)
6576                 {
6577                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6578                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6579                         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);
6580                         Mem_Free(pixels);
6581                 }
6582                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6583                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6584         }
6585
6586         // _luma is supported only for tenebrae compatibility
6587         // _glow is the preferred name
6588         mymiplevel = savemiplevel;
6589         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))))
6590         {
6591                 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);
6592                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6593                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6594                 Mem_Free(pixels);pixels = NULL;
6595         }
6596
6597         mymiplevel = savemiplevel;
6598         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6599         {
6600                 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);
6601                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6602                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6603                 Mem_Free(pixels);
6604                 pixels = NULL;
6605         }
6606
6607         mymiplevel = savemiplevel;
6608         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6609         {
6610                 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);
6611                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6612                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6613                 Mem_Free(pixels);
6614                 pixels = NULL;
6615         }
6616
6617         mymiplevel = savemiplevel;
6618         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6619         {
6620                 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);
6621                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6622                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6623                 Mem_Free(pixels);
6624                 pixels = NULL;
6625         }
6626
6627         mymiplevel = savemiplevel;
6628         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6629         {
6630                 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);
6631                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6632                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6633                 Mem_Free(pixels);
6634                 pixels = NULL;
6635         }
6636
6637         if (basepixels)
6638                 Mem_Free(basepixels);
6639
6640         return skinframe;
6641 }
6642
6643 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6644 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6645 {
6646         int i;
6647         unsigned char *temp1, *temp2;
6648         skinframe_t *skinframe;
6649
6650         if (cls.state == ca_dedicated)
6651                 return NULL;
6652
6653         // if already loaded just return it, otherwise make a new skinframe
6654         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6655         if (skinframe && skinframe->base)
6656                 return skinframe;
6657
6658         skinframe->stain = NULL;
6659         skinframe->merged = NULL;
6660         skinframe->base = NULL;
6661         skinframe->pants = NULL;
6662         skinframe->shirt = NULL;
6663         skinframe->nmap = NULL;
6664         skinframe->gloss = NULL;
6665         skinframe->glow = NULL;
6666         skinframe->fog = NULL;
6667         skinframe->reflect = NULL;
6668         skinframe->hasalpha = false;
6669
6670         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6671         if (!skindata)
6672                 return NULL;
6673
6674         if (developer_loading.integer)
6675                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6676
6677         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6678         {
6679                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6680                 temp2 = temp1 + width * height * 4;
6681                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6682                 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);
6683                 Mem_Free(temp1);
6684         }
6685         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6686         if (textureflags & TEXF_ALPHA)
6687         {
6688                 for (i = 3;i < width * height * 4;i += 4)
6689                 {
6690                         if (skindata[i] < 255)
6691                         {
6692                                 skinframe->hasalpha = true;
6693                                 break;
6694                         }
6695                 }
6696                 if (r_loadfog && skinframe->hasalpha)
6697                 {
6698                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6699                         memcpy(fogpixels, skindata, width * height * 4);
6700                         for (i = 0;i < width * height * 4;i += 4)
6701                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6702                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6703                         Mem_Free(fogpixels);
6704                 }
6705         }
6706
6707         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6708         //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]);
6709
6710         return skinframe;
6711 }
6712
6713 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6714 {
6715         int i;
6716         int featuresmask;
6717         skinframe_t *skinframe;
6718
6719         if (cls.state == ca_dedicated)
6720                 return NULL;
6721
6722         // if already loaded just return it, otherwise make a new skinframe
6723         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6724         if (skinframe && skinframe->base)
6725                 return skinframe;
6726
6727         skinframe->stain = NULL;
6728         skinframe->merged = NULL;
6729         skinframe->base = NULL;
6730         skinframe->pants = NULL;
6731         skinframe->shirt = NULL;
6732         skinframe->nmap = NULL;
6733         skinframe->gloss = NULL;
6734         skinframe->glow = NULL;
6735         skinframe->fog = NULL;
6736         skinframe->reflect = NULL;
6737         skinframe->hasalpha = false;
6738
6739         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6740         if (!skindata)
6741                 return NULL;
6742
6743         if (developer_loading.integer)
6744                 Con_Printf("loading quake skin \"%s\"\n", name);
6745
6746         // 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)
6747         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6748         memcpy(skinframe->qpixels, skindata, width*height);
6749         skinframe->qwidth = width;
6750         skinframe->qheight = height;
6751
6752         featuresmask = 0;
6753         for (i = 0;i < width * height;i++)
6754                 featuresmask |= palette_featureflags[skindata[i]];
6755
6756         skinframe->hasalpha = false;
6757         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6758         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6759         skinframe->qgeneratemerged = true;
6760         skinframe->qgeneratebase = skinframe->qhascolormapping;
6761         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6762
6763         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6764         //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]);
6765
6766         return skinframe;
6767 }
6768
6769 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6770 {
6771         int width;
6772         int height;
6773         unsigned char *skindata;
6774
6775         if (!skinframe->qpixels)
6776                 return;
6777
6778         if (!skinframe->qhascolormapping)
6779                 colormapped = false;
6780
6781         if (colormapped)
6782         {
6783                 if (!skinframe->qgeneratebase)
6784                         return;
6785         }
6786         else
6787         {
6788                 if (!skinframe->qgeneratemerged)
6789                         return;
6790         }
6791
6792         width = skinframe->qwidth;
6793         height = skinframe->qheight;
6794         skindata = skinframe->qpixels;
6795
6796         if (skinframe->qgeneratenmap)
6797         {
6798                 unsigned char *temp1, *temp2;
6799                 skinframe->qgeneratenmap = false;
6800                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6801                 temp2 = temp1 + width * height * 4;
6802                 // use either a custom palette or the quake palette
6803                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6804                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6805                 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);
6806                 Mem_Free(temp1);
6807         }
6808
6809         if (skinframe->qgenerateglow)
6810         {
6811                 skinframe->qgenerateglow = false;
6812                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6813         }
6814
6815         if (colormapped)
6816         {
6817                 skinframe->qgeneratebase = false;
6818                 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);
6819                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6820                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6821         }
6822         else
6823         {
6824                 skinframe->qgeneratemerged = false;
6825                 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);
6826         }
6827
6828         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6829         {
6830                 Mem_Free(skinframe->qpixels);
6831                 skinframe->qpixels = NULL;
6832         }
6833 }
6834
6835 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)
6836 {
6837         int i;
6838         skinframe_t *skinframe;
6839
6840         if (cls.state == ca_dedicated)
6841                 return NULL;
6842
6843         // if already loaded just return it, otherwise make a new skinframe
6844         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6845         if (skinframe && skinframe->base)
6846                 return skinframe;
6847
6848         skinframe->stain = NULL;
6849         skinframe->merged = NULL;
6850         skinframe->base = NULL;
6851         skinframe->pants = NULL;
6852         skinframe->shirt = NULL;
6853         skinframe->nmap = NULL;
6854         skinframe->gloss = NULL;
6855         skinframe->glow = NULL;
6856         skinframe->fog = NULL;
6857         skinframe->reflect = NULL;
6858         skinframe->hasalpha = false;
6859
6860         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6861         if (!skindata)
6862                 return NULL;
6863
6864         if (developer_loading.integer)
6865                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6866
6867         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6868         if (textureflags & TEXF_ALPHA)
6869         {
6870                 for (i = 0;i < width * height;i++)
6871                 {
6872                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6873                         {
6874                                 skinframe->hasalpha = true;
6875                                 break;
6876                         }
6877                 }
6878                 if (r_loadfog && skinframe->hasalpha)
6879                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6880         }
6881
6882         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6883         //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]);
6884
6885         return skinframe;
6886 }
6887
6888 skinframe_t *R_SkinFrame_LoadMissing(void)
6889 {
6890         skinframe_t *skinframe;
6891
6892         if (cls.state == ca_dedicated)
6893                 return NULL;
6894
6895         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6896         skinframe->stain = NULL;
6897         skinframe->merged = NULL;
6898         skinframe->base = NULL;
6899         skinframe->pants = NULL;
6900         skinframe->shirt = NULL;
6901         skinframe->nmap = NULL;
6902         skinframe->gloss = NULL;
6903         skinframe->glow = NULL;
6904         skinframe->fog = NULL;
6905         skinframe->reflect = NULL;
6906         skinframe->hasalpha = false;
6907
6908         skinframe->avgcolor[0] = rand() / RAND_MAX;
6909         skinframe->avgcolor[1] = rand() / RAND_MAX;
6910         skinframe->avgcolor[2] = rand() / RAND_MAX;
6911         skinframe->avgcolor[3] = 1;
6912
6913         return skinframe;
6914 }
6915
6916 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6917 typedef struct suffixinfo_s
6918 {
6919         const char *suffix;
6920         qboolean flipx, flipy, flipdiagonal;
6921 }
6922 suffixinfo_t;
6923 static suffixinfo_t suffix[3][6] =
6924 {
6925         {
6926                 {"px",   false, false, false},
6927                 {"nx",   false, false, false},
6928                 {"py",   false, false, false},
6929                 {"ny",   false, false, false},
6930                 {"pz",   false, false, false},
6931                 {"nz",   false, false, false}
6932         },
6933         {
6934                 {"posx", false, false, false},
6935                 {"negx", false, false, false},
6936                 {"posy", false, false, false},
6937                 {"negy", false, false, false},
6938                 {"posz", false, false, false},
6939                 {"negz", false, false, false}
6940         },
6941         {
6942                 {"rt",    true, false,  true},
6943                 {"lf",   false,  true,  true},
6944                 {"ft",    true,  true, false},
6945                 {"bk",   false, false, false},
6946                 {"up",    true, false,  true},
6947                 {"dn",    true, false,  true}
6948         }
6949 };
6950
6951 static int componentorder[4] = {0, 1, 2, 3};
6952
6953 rtexture_t *R_LoadCubemap(const char *basename)
6954 {
6955         int i, j, cubemapsize;
6956         unsigned char *cubemappixels, *image_buffer;
6957         rtexture_t *cubemaptexture;
6958         char name[256];
6959         // must start 0 so the first loadimagepixels has no requested width/height
6960         cubemapsize = 0;
6961         cubemappixels = NULL;
6962         cubemaptexture = NULL;
6963         // keep trying different suffix groups (posx, px, rt) until one loads
6964         for (j = 0;j < 3 && !cubemappixels;j++)
6965         {
6966                 // load the 6 images in the suffix group
6967                 for (i = 0;i < 6;i++)
6968                 {
6969                         // generate an image name based on the base and and suffix
6970                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6971                         // load it
6972                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6973                         {
6974                                 // an image loaded, make sure width and height are equal
6975                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6976                                 {
6977                                         // if this is the first image to load successfully, allocate the cubemap memory
6978                                         if (!cubemappixels && image_width >= 1)
6979                                         {
6980                                                 cubemapsize = image_width;
6981                                                 // note this clears to black, so unavailable sides are black
6982                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6983                                         }
6984                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6985                                         if (cubemappixels)
6986                                                 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);
6987                                 }
6988                                 else
6989                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6990                                 // free the image
6991                                 Mem_Free(image_buffer);
6992                         }
6993                 }
6994         }
6995         // if a cubemap loaded, upload it
6996         if (cubemappixels)
6997         {
6998                 if (developer_loading.integer)
6999                         Con_Printf("loading cubemap \"%s\"\n", basename);
7000
7001                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7002                 Mem_Free(cubemappixels);
7003         }
7004         else
7005         {
7006                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7007                 if (developer_loading.integer)
7008                 {
7009                         Con_Printf("(tried tried images ");
7010                         for (j = 0;j < 3;j++)
7011                                 for (i = 0;i < 6;i++)
7012                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7013                         Con_Print(" and was unable to find any of them).\n");
7014                 }
7015         }
7016         return cubemaptexture;
7017 }
7018
7019 rtexture_t *R_GetCubemap(const char *basename)
7020 {
7021         int i;
7022         for (i = 0;i < r_texture_numcubemaps;i++)
7023                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7024                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7025         if (i >= MAX_CUBEMAPS)
7026                 return r_texture_whitecube;
7027         r_texture_numcubemaps++;
7028         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7029         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7030         return r_texture_cubemaps[i].texture;
7031 }
7032
7033 void R_FreeCubemaps(void)
7034 {
7035         int i;
7036         for (i = 0;i < r_texture_numcubemaps;i++)
7037         {
7038                 if (developer_loading.integer)
7039                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7040                 if (r_texture_cubemaps[i].texture)
7041                         R_FreeTexture(r_texture_cubemaps[i].texture);
7042         }
7043         r_texture_numcubemaps = 0;
7044 }
7045
7046 void R_Main_FreeViewCache(void)
7047 {
7048         if (r_refdef.viewcache.entityvisible)
7049                 Mem_Free(r_refdef.viewcache.entityvisible);
7050         if (r_refdef.viewcache.world_pvsbits)
7051                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7052         if (r_refdef.viewcache.world_leafvisible)
7053                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7054         if (r_refdef.viewcache.world_surfacevisible)
7055                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7056         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7057 }
7058
7059 void R_Main_ResizeViewCache(void)
7060 {
7061         int numentities = r_refdef.scene.numentities;
7062         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7063         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7064         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7065         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7066         if (r_refdef.viewcache.maxentities < numentities)
7067         {
7068                 r_refdef.viewcache.maxentities = numentities;
7069                 if (r_refdef.viewcache.entityvisible)
7070                         Mem_Free(r_refdef.viewcache.entityvisible);
7071                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7072         }
7073         if (r_refdef.viewcache.world_numclusters != numclusters)
7074         {
7075                 r_refdef.viewcache.world_numclusters = numclusters;
7076                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7077                 if (r_refdef.viewcache.world_pvsbits)
7078                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7079                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7080         }
7081         if (r_refdef.viewcache.world_numleafs != numleafs)
7082         {
7083                 r_refdef.viewcache.world_numleafs = numleafs;
7084                 if (r_refdef.viewcache.world_leafvisible)
7085                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7086                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7087         }
7088         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7089         {
7090                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7091                 if (r_refdef.viewcache.world_surfacevisible)
7092                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7093                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7094         }
7095 }
7096
7097 extern rtexture_t *loadingscreentexture;
7098 void gl_main_start(void)
7099 {
7100         loadingscreentexture = NULL;
7101         r_texture_blanknormalmap = NULL;
7102         r_texture_white = NULL;
7103         r_texture_grey128 = NULL;
7104         r_texture_black = NULL;
7105         r_texture_whitecube = NULL;
7106         r_texture_normalizationcube = NULL;
7107         r_texture_fogattenuation = NULL;
7108         r_texture_fogheighttexture = NULL;
7109         r_texture_gammaramps = NULL;
7110         r_texture_numcubemaps = 0;
7111
7112         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7113         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7114
7115         switch(vid.renderpath)
7116         {
7117         case RENDERPATH_GL20:
7118         case RENDERPATH_CGGL:
7119         case RENDERPATH_D3D9:
7120         case RENDERPATH_D3D10:
7121         case RENDERPATH_D3D11:
7122                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7123                 Cvar_SetValueQuick(&gl_combine, 1);
7124                 Cvar_SetValueQuick(&r_glsl, 1);
7125                 r_loadnormalmap = true;
7126                 r_loadgloss = true;
7127                 r_loadfog = false;
7128                 break;
7129         case RENDERPATH_GL13:
7130                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7131                 Cvar_SetValueQuick(&gl_combine, 1);
7132                 Cvar_SetValueQuick(&r_glsl, 0);
7133                 r_loadnormalmap = false;
7134                 r_loadgloss = false;
7135                 r_loadfog = true;
7136                 break;
7137         case RENDERPATH_GL11:
7138                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7139                 Cvar_SetValueQuick(&gl_combine, 0);
7140                 Cvar_SetValueQuick(&r_glsl, 0);
7141                 r_loadnormalmap = false;
7142                 r_loadgloss = false;
7143                 r_loadfog = true;
7144                 break;
7145         }
7146
7147         R_AnimCache_Free();
7148         R_FrameData_Reset();
7149
7150         r_numqueries = 0;
7151         r_maxqueries = 0;
7152         memset(r_queries, 0, sizeof(r_queries));
7153
7154         r_qwskincache = NULL;
7155         r_qwskincache_size = 0;
7156
7157         // set up r_skinframe loading system for textures
7158         memset(&r_skinframe, 0, sizeof(r_skinframe));
7159         r_skinframe.loadsequence = 1;
7160         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7161
7162         r_main_texturepool = R_AllocTexturePool();
7163         R_BuildBlankTextures();
7164         R_BuildNoTexture();
7165         if (vid.support.arb_texture_cube_map)
7166         {
7167                 R_BuildWhiteCube();
7168                 R_BuildNormalizationCube();
7169         }
7170         r_texture_fogattenuation = NULL;
7171         r_texture_fogheighttexture = NULL;
7172         r_texture_gammaramps = NULL;
7173         //r_texture_fogintensity = NULL;
7174         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7175         memset(&r_waterstate, 0, sizeof(r_waterstate));
7176         r_glsl_permutation = NULL;
7177         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7178         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7179         glslshaderstring = NULL;
7180 #ifdef SUPPORTCG
7181         r_cg_permutation = NULL;
7182         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7183         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7184         cgshaderstring = NULL;
7185 #endif
7186 #ifdef SUPPORTD3D
7187         r_hlsl_permutation = NULL;
7188         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7189         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7190         hlslshaderstring = NULL;
7191 #endif
7192         memset(&r_svbsp, 0, sizeof (r_svbsp));
7193
7194         r_refdef.fogmasktable_density = 0;
7195 }
7196
7197 void gl_main_shutdown(void)
7198 {
7199         R_AnimCache_Free();
7200         R_FrameData_Reset();
7201
7202         R_Main_FreeViewCache();
7203
7204         switch(vid.renderpath)
7205         {
7206         case RENDERPATH_GL11:
7207         case RENDERPATH_GL13:
7208         case RENDERPATH_GL20:
7209         case RENDERPATH_CGGL:
7210                 if (r_maxqueries)
7211                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7212                 break;
7213         case RENDERPATH_D3D9:
7214                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7215                 break;
7216         case RENDERPATH_D3D10:
7217                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7218                 break;
7219         case RENDERPATH_D3D11:
7220                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7221                 break;
7222         }
7223
7224         r_numqueries = 0;
7225         r_maxqueries = 0;
7226         memset(r_queries, 0, sizeof(r_queries));
7227
7228         r_qwskincache = NULL;
7229         r_qwskincache_size = 0;
7230
7231         // clear out the r_skinframe state
7232         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7233         memset(&r_skinframe, 0, sizeof(r_skinframe));
7234
7235         if (r_svbsp.nodes)
7236                 Mem_Free(r_svbsp.nodes);
7237         memset(&r_svbsp, 0, sizeof (r_svbsp));
7238         R_FreeTexturePool(&r_main_texturepool);
7239         loadingscreentexture = NULL;
7240         r_texture_blanknormalmap = NULL;
7241         r_texture_white = NULL;
7242         r_texture_grey128 = NULL;
7243         r_texture_black = NULL;
7244         r_texture_whitecube = NULL;
7245         r_texture_normalizationcube = NULL;
7246         r_texture_fogattenuation = NULL;
7247         r_texture_fogheighttexture = NULL;
7248         r_texture_gammaramps = NULL;
7249         r_texture_numcubemaps = 0;
7250         //r_texture_fogintensity = NULL;
7251         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7252         memset(&r_waterstate, 0, sizeof(r_waterstate));
7253         R_GLSL_Restart_f();
7254 }
7255
7256 extern void CL_ParseEntityLump(char *entitystring);
7257 void gl_main_newmap(void)
7258 {
7259         // FIXME: move this code to client
7260         char *entities, entname[MAX_QPATH];
7261         if (r_qwskincache)
7262                 Mem_Free(r_qwskincache);
7263         r_qwskincache = NULL;
7264         r_qwskincache_size = 0;
7265         if (cl.worldmodel)
7266         {
7267                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7268                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7269                 {
7270                         CL_ParseEntityLump(entities);
7271                         Mem_Free(entities);
7272                         return;
7273                 }
7274                 if (cl.worldmodel->brush.entities)
7275                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7276         }
7277         R_Main_FreeViewCache();
7278
7279         R_FrameData_Reset();
7280 }
7281
7282 void GL_Main_Init(void)
7283 {
7284         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7285
7286         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7287         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7288         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7289         if (gamemode == GAME_NEHAHRA)
7290         {
7291                 Cvar_RegisterVariable (&gl_fogenable);
7292                 Cvar_RegisterVariable (&gl_fogdensity);
7293                 Cvar_RegisterVariable (&gl_fogred);
7294                 Cvar_RegisterVariable (&gl_foggreen);
7295                 Cvar_RegisterVariable (&gl_fogblue);
7296                 Cvar_RegisterVariable (&gl_fogstart);
7297                 Cvar_RegisterVariable (&gl_fogend);
7298                 Cvar_RegisterVariable (&gl_skyclip);
7299         }
7300         Cvar_RegisterVariable(&r_motionblur);
7301         Cvar_RegisterVariable(&r_motionblur_maxblur);
7302         Cvar_RegisterVariable(&r_motionblur_bmin);
7303         Cvar_RegisterVariable(&r_motionblur_vmin);
7304         Cvar_RegisterVariable(&r_motionblur_vmax);
7305         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7306         Cvar_RegisterVariable(&r_motionblur_randomize);
7307         Cvar_RegisterVariable(&r_damageblur);
7308         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7309         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7310         Cvar_RegisterVariable(&r_equalize_entities_by);
7311         Cvar_RegisterVariable(&r_equalize_entities_to);
7312         Cvar_RegisterVariable(&r_depthfirst);
7313         Cvar_RegisterVariable(&r_useinfinitefarclip);
7314         Cvar_RegisterVariable(&r_farclip_base);
7315         Cvar_RegisterVariable(&r_farclip_world);
7316         Cvar_RegisterVariable(&r_nearclip);
7317         Cvar_RegisterVariable(&r_showbboxes);
7318         Cvar_RegisterVariable(&r_showsurfaces);
7319         Cvar_RegisterVariable(&r_showtris);
7320         Cvar_RegisterVariable(&r_shownormals);
7321         Cvar_RegisterVariable(&r_showlighting);
7322         Cvar_RegisterVariable(&r_showshadowvolumes);
7323         Cvar_RegisterVariable(&r_showcollisionbrushes);
7324         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7325         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7326         Cvar_RegisterVariable(&r_showdisabledepthtest);
7327         Cvar_RegisterVariable(&r_drawportals);
7328         Cvar_RegisterVariable(&r_drawentities);
7329         Cvar_RegisterVariable(&r_draw2d);
7330         Cvar_RegisterVariable(&r_drawworld);
7331         Cvar_RegisterVariable(&r_cullentities_trace);
7332         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7333         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7334         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7335         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7336         Cvar_RegisterVariable(&r_drawviewmodel);
7337         Cvar_RegisterVariable(&r_drawexteriormodel);
7338         Cvar_RegisterVariable(&r_speeds);
7339         Cvar_RegisterVariable(&r_fullbrights);
7340         Cvar_RegisterVariable(&r_wateralpha);
7341         Cvar_RegisterVariable(&r_dynamic);
7342         Cvar_RegisterVariable(&r_fakelight);
7343         Cvar_RegisterVariable(&r_fakelight_intensity);
7344         Cvar_RegisterVariable(&r_fullbright);
7345         Cvar_RegisterVariable(&r_shadows);
7346         Cvar_RegisterVariable(&r_shadows_darken);
7347         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7348         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7349         Cvar_RegisterVariable(&r_shadows_throwdistance);
7350         Cvar_RegisterVariable(&r_shadows_throwdirection);
7351         Cvar_RegisterVariable(&r_shadows_focus);
7352         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7353         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7354         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7355         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7356         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7357         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7358         Cvar_RegisterVariable(&r_fog_exp2);
7359         Cvar_RegisterVariable(&r_drawfog);
7360         Cvar_RegisterVariable(&r_transparentdepthmasking);
7361         Cvar_RegisterVariable(&r_texture_dds_load);
7362         Cvar_RegisterVariable(&r_texture_dds_save);
7363         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7364         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7365         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7366         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7367         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7368         Cvar_RegisterVariable(&r_textureunits);
7369         Cvar_RegisterVariable(&gl_combine);
7370         Cvar_RegisterVariable(&r_glsl);
7371         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7372         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7373         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7374         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7375         Cvar_RegisterVariable(&r_glsl_postprocess);
7376         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7377         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7378         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7379         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7380         Cvar_RegisterVariable(&r_water);
7381         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7382         Cvar_RegisterVariable(&r_water_clippingplanebias);
7383         Cvar_RegisterVariable(&r_water_refractdistort);
7384         Cvar_RegisterVariable(&r_water_reflectdistort);
7385         Cvar_RegisterVariable(&r_water_scissormode);
7386         Cvar_RegisterVariable(&r_lerpsprites);
7387         Cvar_RegisterVariable(&r_lerpmodels);
7388         Cvar_RegisterVariable(&r_lerplightstyles);
7389         Cvar_RegisterVariable(&r_waterscroll);
7390         Cvar_RegisterVariable(&r_bloom);
7391         Cvar_RegisterVariable(&r_bloom_colorscale);
7392         Cvar_RegisterVariable(&r_bloom_brighten);
7393         Cvar_RegisterVariable(&r_bloom_blur);
7394         Cvar_RegisterVariable(&r_bloom_resolution);
7395         Cvar_RegisterVariable(&r_bloom_colorexponent);
7396         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7397         Cvar_RegisterVariable(&r_hdr);
7398         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7399         Cvar_RegisterVariable(&r_hdr_glowintensity);
7400         Cvar_RegisterVariable(&r_hdr_range);
7401         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7402         Cvar_RegisterVariable(&developer_texturelogging);
7403         Cvar_RegisterVariable(&gl_lightmaps);
7404         Cvar_RegisterVariable(&r_test);
7405         Cvar_RegisterVariable(&r_glsl_saturation);
7406         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7407         Cvar_RegisterVariable(&r_framedatasize);
7408         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7409                 Cvar_SetValue("r_fullbrights", 0);
7410         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7411
7412         Cvar_RegisterVariable(&r_track_sprites);
7413         Cvar_RegisterVariable(&r_track_sprites_flags);
7414         Cvar_RegisterVariable(&r_track_sprites_scalew);
7415         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7416         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7417         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7418 }
7419
7420 extern void R_Textures_Init(void);
7421 extern void GL_Draw_Init(void);
7422 extern void GL_Main_Init(void);
7423 extern void R_Shadow_Init(void);
7424 extern void R_Sky_Init(void);
7425 extern void GL_Surf_Init(void);
7426 extern void R_Particles_Init(void);
7427 extern void R_Explosion_Init(void);
7428 extern void gl_backend_init(void);
7429 extern void Sbar_Init(void);
7430 extern void R_LightningBeams_Init(void);
7431 extern void Mod_RenderInit(void);
7432 extern void Font_Init(void);
7433
7434 void Render_Init(void)
7435 {
7436         gl_backend_init();
7437         R_Textures_Init();
7438         GL_Main_Init();
7439         Font_Init();
7440         GL_Draw_Init();
7441         R_Shadow_Init();
7442         R_Sky_Init();
7443         GL_Surf_Init();
7444         Sbar_Init();
7445         R_Particles_Init();
7446         R_Explosion_Init();
7447         R_LightningBeams_Init();
7448         Mod_RenderInit();
7449 }
7450
7451 /*
7452 ===============
7453 GL_Init
7454 ===============
7455 */
7456 extern char *ENGINE_EXTENSIONS;
7457 void GL_Init (void)
7458 {
7459         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7460         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7461         gl_version = (const char *)qglGetString(GL_VERSION);
7462         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7463
7464         if (!gl_extensions)
7465                 gl_extensions = "";
7466         if (!gl_platformextensions)
7467                 gl_platformextensions = "";
7468
7469         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7470         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7471         Con_Printf("GL_VERSION: %s\n", gl_version);
7472         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7473         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7474
7475         VID_CheckExtensions();
7476
7477         // LordHavoc: report supported extensions
7478         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7479
7480         // clear to black (loading plaque will be seen over this)
7481         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7482 }
7483
7484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7485 {
7486         int i;
7487         mplane_t *p;
7488         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7489         {
7490                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7491                 if (i == 4)
7492                         continue;
7493                 p = r_refdef.view.frustum + i;
7494                 switch(p->signbits)
7495                 {
7496                 default:
7497                 case 0:
7498                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7499                                 return true;
7500                         break;
7501                 case 1:
7502                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7503                                 return true;
7504                         break;
7505                 case 2:
7506                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7507                                 return true;
7508                         break;
7509                 case 3:
7510                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7511                                 return true;
7512                         break;
7513                 case 4:
7514                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7515                                 return true;
7516                         break;
7517                 case 5:
7518                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7519                                 return true;
7520                         break;
7521                 case 6:
7522                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7523                                 return true;
7524                         break;
7525                 case 7:
7526                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7527                                 return true;
7528                         break;
7529                 }
7530         }
7531         return false;
7532 }
7533
7534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7535 {
7536         int i;
7537         const mplane_t *p;
7538         for (i = 0;i < numplanes;i++)
7539         {
7540                 p = planes + i;
7541                 switch(p->signbits)
7542                 {
7543                 default:
7544                 case 0:
7545                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 1:
7549                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 case 2:
7553                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7554                                 return true;
7555                         break;
7556                 case 3:
7557                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7558                                 return true;
7559                         break;
7560                 case 4:
7561                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7562                                 return true;
7563                         break;
7564                 case 5:
7565                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7566                                 return true;
7567                         break;
7568                 case 6:
7569                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7570                                 return true;
7571                         break;
7572                 case 7:
7573                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7574                                 return true;
7575                         break;
7576                 }
7577         }
7578         return false;
7579 }
7580
7581 //==================================================================================
7582
7583 // LordHavoc: this stores temporary data used within the same frame
7584
7585 qboolean r_framedata_failed;
7586 static size_t r_framedata_size;
7587 static size_t r_framedata_current;
7588 static void *r_framedata_base;
7589
7590 void R_FrameData_Reset(void)
7591 {
7592         if (r_framedata_base)
7593                 Mem_Free(r_framedata_base);
7594         r_framedata_base = NULL;
7595         r_framedata_size = 0;
7596         r_framedata_current = 0;
7597         r_framedata_failed = false;
7598 }
7599
7600 void R_FrameData_NewFrame(void)
7601 {
7602         size_t wantedsize;
7603         if (r_framedata_failed)
7604                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7605         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7606         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7607         if (r_framedata_size != wantedsize)
7608         {
7609                 r_framedata_size = wantedsize;
7610                 if (r_framedata_base)
7611                         Mem_Free(r_framedata_base);
7612                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7613         }
7614         r_framedata_current = 0;
7615         r_framedata_failed = false;
7616 }
7617
7618 void *R_FrameData_Alloc(size_t size)
7619 {
7620         void *data;
7621
7622         // align to 16 byte boundary
7623         size = (size + 15) & ~15;
7624         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7625         r_framedata_current += size;
7626
7627         // check overflow
7628         if (r_framedata_current > r_framedata_size)
7629                 r_framedata_failed = true;
7630
7631         // return NULL on everything after a failure
7632         if (r_framedata_failed)
7633                 return NULL;
7634
7635         return data;
7636 }
7637
7638 void *R_FrameData_Store(size_t size, void *data)
7639 {
7640         void *d = R_FrameData_Alloc(size);
7641         if (d)
7642                 memcpy(d, data, size);
7643         return d;
7644 }
7645
7646 //==================================================================================
7647
7648 // LordHavoc: animcache originally written by Echon, rewritten since then
7649
7650 /**
7651  * Animation cache prevents re-generating mesh data for an animated model
7652  * multiple times in one frame for lighting, shadowing, reflections, etc.
7653  */
7654
7655 void R_AnimCache_Free(void)
7656 {
7657 }
7658
7659 void R_AnimCache_ClearCache(void)
7660 {
7661         int i;
7662         entity_render_t *ent;
7663
7664         for (i = 0;i < r_refdef.scene.numentities;i++)
7665         {
7666                 ent = r_refdef.scene.entities[i];
7667                 ent->animcache_vertex3f = NULL;
7668                 ent->animcache_normal3f = NULL;
7669                 ent->animcache_svector3f = NULL;
7670                 ent->animcache_tvector3f = NULL;
7671                 ent->animcache_vertexposition = NULL;
7672                 ent->animcache_vertexmesh = NULL;
7673                 ent->animcache_vertexpositionbuffer = NULL;
7674                 ent->animcache_vertexmeshbuffer = NULL;
7675         }
7676 }
7677
7678 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7679 {
7680         int i;
7681
7682         // identical memory layout, so no need to allocate...
7683         // this also provides the vertexposition structure to everything, e.g.
7684         // depth masked rendering currently uses it even if having separate
7685         // arrays
7686         // NOTE: get rid of this optimization if changing it to e.g. 4f
7687         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7688
7689         // TODO:
7690         // get rid of following uses of VERTEXPOSITION, change to the array:
7691         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7692         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7693         // R_DrawTextureSurfaceList_DepthOnly
7694         // R_Q1BSP_DrawShadowMap
7695
7696         switch(vid.renderpath)
7697         {
7698         case RENDERPATH_GL20:
7699         case RENDERPATH_CGGL:
7700                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7701                 if (gl_mesh_separatearrays.integer)
7702                         return;
7703                 break;
7704         case RENDERPATH_D3D9:
7705         case RENDERPATH_D3D10:
7706         case RENDERPATH_D3D11:
7707                 // always need the meshbuffers
7708                 break;
7709         case RENDERPATH_GL13:
7710         case RENDERPATH_GL11:
7711                 // never need the meshbuffers
7712                 return;
7713         }
7714
7715         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7716                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7717         /*
7718         if (!ent->animcache_vertexposition)
7719                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7720         */
7721         if (ent->animcache_vertexposition)
7722         {
7723                 /*
7724                 for (i = 0;i < numvertices;i++)
7725                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7726                 */
7727                 // TODO: upload vertex buffer?
7728         }
7729         if (ent->animcache_vertexmesh)
7730         {
7731                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7732                 for (i = 0;i < numvertices;i++)
7733                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7734                 if (ent->animcache_svector3f)
7735                         for (i = 0;i < numvertices;i++)
7736                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7737                 if (ent->animcache_tvector3f)
7738                         for (i = 0;i < numvertices;i++)
7739                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7740                 if (ent->animcache_normal3f)
7741                         for (i = 0;i < numvertices;i++)
7742                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7743                 // TODO: upload vertex buffer?
7744         }
7745 }
7746
7747 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7748 {
7749         dp_model_t *model = ent->model;
7750         int numvertices;
7751         // see if it's already cached this frame
7752         if (ent->animcache_vertex3f)
7753         {
7754                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7755                 if (wantnormals || wanttangents)
7756                 {
7757                         if (ent->animcache_normal3f)
7758                                 wantnormals = false;
7759                         if (ent->animcache_svector3f)
7760                                 wanttangents = false;
7761                         if (wantnormals || wanttangents)
7762                         {
7763                                 numvertices = model->surfmesh.num_vertices;
7764                                 if (wantnormals)
7765                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7766                                 if (wanttangents)
7767                                 {
7768                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7769                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7770                                 }
7771                                 if (!r_framedata_failed)
7772                                 {
7773                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7774                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7775                                 }
7776                         }
7777                 }
7778         }
7779         else
7780         {
7781                 // see if this ent is worth caching
7782                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7783                         return false;
7784                 // get some memory for this entity and generate mesh data
7785                 numvertices = model->surfmesh.num_vertices;
7786                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7787                 if (wantnormals)
7788                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7789                 if (wanttangents)
7790                 {
7791                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7792                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7793                 }
7794                 if (!r_framedata_failed)
7795                 {
7796                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7797                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7798                 }
7799         }
7800         return !r_framedata_failed;
7801 }
7802
7803 void R_AnimCache_CacheVisibleEntities(void)
7804 {
7805         int i;
7806         qboolean wantnormals = true;
7807         qboolean wanttangents = !r_showsurfaces.integer;
7808
7809         switch(vid.renderpath)
7810         {
7811         case RENDERPATH_GL20:
7812         case RENDERPATH_CGGL:
7813         case RENDERPATH_D3D9:
7814         case RENDERPATH_D3D10:
7815         case RENDERPATH_D3D11:
7816                 break;
7817         case RENDERPATH_GL13:
7818         case RENDERPATH_GL11:
7819                 wanttangents = false;
7820                 break;
7821         }
7822
7823         if (r_shownormals.integer)
7824                 wanttangents = wantnormals = true;
7825
7826         // TODO: thread this
7827         // NOTE: R_PrepareRTLights() also caches entities
7828
7829         for (i = 0;i < r_refdef.scene.numentities;i++)
7830                 if (r_refdef.viewcache.entityvisible[i])
7831                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7832 }
7833
7834 //==================================================================================
7835
7836 static void R_View_UpdateEntityLighting (void)
7837 {
7838         int i;
7839         entity_render_t *ent;
7840         vec3_t tempdiffusenormal, avg;
7841         vec_t f, fa, fd, fdd;
7842         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7843
7844         for (i = 0;i < r_refdef.scene.numentities;i++)
7845         {
7846                 ent = r_refdef.scene.entities[i];
7847
7848                 // skip unseen models
7849                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7850                         continue;
7851
7852                 // skip bsp models
7853                 if (ent->model && ent->model->brush.num_leafs)
7854                 {
7855                         // TODO: use modellight for r_ambient settings on world?
7856                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7857                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7858                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7859                         continue;
7860                 }
7861
7862                 // fetch the lighting from the worldmodel data
7863                 VectorClear(ent->modellight_ambient);
7864                 VectorClear(ent->modellight_diffuse);
7865                 VectorClear(tempdiffusenormal);
7866                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7867                 {
7868                         vec3_t org;
7869                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7870
7871                         // complete lightning for lit sprites
7872                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7873                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7874                         {
7875                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7876                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7877                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7878                         }
7879                         else
7880                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7881
7882                         if(ent->flags & RENDER_EQUALIZE)
7883                         {
7884                                 // first fix up ambient lighting...
7885                                 if(r_equalize_entities_minambient.value > 0)
7886                                 {
7887                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7888                                         if(fd > 0)
7889                                         {
7890                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7891                                                 if(fa < r_equalize_entities_minambient.value * fd)
7892                                                 {
7893                                                         // solve:
7894                                                         //   fa'/fd' = minambient
7895                                                         //   fa'+0.25*fd' = fa+0.25*fd
7896                                                         //   ...
7897                                                         //   fa' = fd' * minambient
7898                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7899                                                         //   ...
7900                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7901                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7902                                                         //   ...
7903                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7904                                                         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
7905                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7906                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7907                                                 }
7908                                         }
7909                                 }
7910
7911                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7912                                 {
7913                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7914                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7915                                         if(f > 0)
7916                                         {
7917                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7918                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7919                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7920                                         }
7921                                 }
7922                         }
7923                 }
7924                 else // highly rare
7925                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7926
7927                 // move the light direction into modelspace coordinates for lighting code
7928                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7929                 if(VectorLength2(ent->modellight_lightdir) == 0)
7930                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7931                 VectorNormalize(ent->modellight_lightdir);
7932         }
7933 }
7934
7935 #define MAX_LINEOFSIGHTTRACES 64
7936
7937 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7938 {
7939         int i;
7940         vec3_t boxmins, boxmaxs;
7941         vec3_t start;
7942         vec3_t end;
7943         dp_model_t *model = r_refdef.scene.worldmodel;
7944
7945         if (!model || !model->brush.TraceLineOfSight)
7946                 return true;
7947
7948         // expand the box a little
7949         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7950         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7951         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7952         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7953         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7954         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7955
7956         // return true if eye is inside enlarged box
7957         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7958                 return true;
7959
7960         // try center
7961         VectorCopy(eye, start);
7962         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7963         if (model->brush.TraceLineOfSight(model, start, end))
7964                 return true;
7965
7966         // try various random positions
7967         for (i = 0;i < numsamples;i++)
7968         {
7969                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7970                 if (model->brush.TraceLineOfSight(model, start, end))
7971                         return true;
7972         }
7973
7974         return false;
7975 }
7976
7977
7978 static void R_View_UpdateEntityVisible (void)
7979 {
7980         int i;
7981         int renderimask;
7982         int samples;
7983         entity_render_t *ent;
7984
7985         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7986                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7987                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7988                 :                                                          RENDER_EXTERIORMODEL;
7989         if (!r_drawviewmodel.integer)
7990                 renderimask |= RENDER_VIEWMODEL;
7991         if (!r_drawexteriormodel.integer)
7992                 renderimask |= RENDER_EXTERIORMODEL;
7993         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7994         {
7995                 // worldmodel can check visibility
7996                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7997                 for (i = 0;i < r_refdef.scene.numentities;i++)
7998                 {
7999                         ent = r_refdef.scene.entities[i];
8000                         if (!(ent->flags & renderimask))
8001                         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)))
8002                         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))
8003                                 r_refdef.viewcache.entityvisible[i] = true;
8004                 }
8005                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8006                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8007                 {
8008                         for (i = 0;i < r_refdef.scene.numentities;i++)
8009                         {
8010                                 ent = r_refdef.scene.entities[i];
8011                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8012                                 {
8013                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8014                                         if (samples < 0)
8015                                                 continue; // temp entities do pvs only
8016                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8017                                                 ent->last_trace_visibility = realtime;
8018                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8019                                                 r_refdef.viewcache.entityvisible[i] = 0;
8020                                 }
8021                         }
8022                 }
8023         }
8024         else
8025         {
8026                 // no worldmodel or it can't check visibility
8027                 for (i = 0;i < r_refdef.scene.numentities;i++)
8028                 {
8029                         ent = r_refdef.scene.entities[i];
8030                         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));
8031                 }
8032         }
8033 }
8034
8035 /// only used if skyrendermasked, and normally returns false
8036 int R_DrawBrushModelsSky (void)
8037 {
8038         int i, sky;
8039         entity_render_t *ent;
8040
8041         sky = false;
8042         for (i = 0;i < r_refdef.scene.numentities;i++)
8043         {
8044                 if (!r_refdef.viewcache.entityvisible[i])
8045                         continue;
8046                 ent = r_refdef.scene.entities[i];
8047                 if (!ent->model || !ent->model->DrawSky)
8048                         continue;
8049                 ent->model->DrawSky(ent);
8050                 sky = true;
8051         }
8052         return sky;
8053 }
8054
8055 static void R_DrawNoModel(entity_render_t *ent);
8056 static void R_DrawModels(void)
8057 {
8058         int i;
8059         entity_render_t *ent;
8060
8061         for (i = 0;i < r_refdef.scene.numentities;i++)
8062         {
8063                 if (!r_refdef.viewcache.entityvisible[i])
8064                         continue;
8065                 ent = r_refdef.scene.entities[i];
8066                 r_refdef.stats.entities++;
8067                 if (ent->model && ent->model->Draw != NULL)
8068                         ent->model->Draw(ent);
8069                 else
8070                         R_DrawNoModel(ent);
8071         }
8072 }
8073
8074 static void R_DrawModelsDepth(void)
8075 {
8076         int i;
8077         entity_render_t *ent;
8078
8079         for (i = 0;i < r_refdef.scene.numentities;i++)
8080         {
8081                 if (!r_refdef.viewcache.entityvisible[i])
8082                         continue;
8083                 ent = r_refdef.scene.entities[i];
8084                 if (ent->model && ent->model->DrawDepth != NULL)
8085                         ent->model->DrawDepth(ent);
8086         }
8087 }
8088
8089 static void R_DrawModelsDebug(void)
8090 {
8091         int i;
8092         entity_render_t *ent;
8093
8094         for (i = 0;i < r_refdef.scene.numentities;i++)
8095         {
8096                 if (!r_refdef.viewcache.entityvisible[i])
8097                         continue;
8098                 ent = r_refdef.scene.entities[i];
8099                 if (ent->model && ent->model->DrawDebug != NULL)
8100                         ent->model->DrawDebug(ent);
8101         }
8102 }
8103
8104 static void R_DrawModelsAddWaterPlanes(void)
8105 {
8106         int i;
8107         entity_render_t *ent;
8108
8109         for (i = 0;i < r_refdef.scene.numentities;i++)
8110         {
8111                 if (!r_refdef.viewcache.entityvisible[i])
8112                         continue;
8113                 ent = r_refdef.scene.entities[i];
8114                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8115                         ent->model->DrawAddWaterPlanes(ent);
8116         }
8117 }
8118
8119 static void R_View_SetFrustum(const int *scissor)
8120 {
8121         int i;
8122         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8123         vec3_t forward, left, up, origin, v;
8124
8125         if(scissor)
8126         {
8127                 // flipped x coordinates (because x points left here)
8128                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8129                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8130
8131                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8132                 switch(vid.renderpath)
8133                 {
8134                         case RENDERPATH_D3D9:
8135                         case RENDERPATH_D3D10:
8136                         case RENDERPATH_D3D11:
8137                                 // non-flipped y coordinates
8138                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8139                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8140                                 break;
8141                         case RENDERPATH_GL11:
8142                         case RENDERPATH_GL13:
8143                         case RENDERPATH_GL20:
8144                         case RENDERPATH_CGGL:
8145                                 // non-flipped y coordinates
8146                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8147                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8148                                 break;
8149                 }
8150         }
8151
8152         // we can't trust r_refdef.view.forward and friends in reflected scenes
8153         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8154
8155 #if 0
8156         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8157         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8158         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8159         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8160         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8161         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8162         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8163         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8164         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8165         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8166         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8167         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8168 #endif
8169
8170 #if 0
8171         zNear = r_refdef.nearclip;
8172         nudge = 1.0 - 1.0 / (1<<23);
8173         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8174         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8175         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8176         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8177         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8178         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8179         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8180         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8181 #endif
8182
8183
8184
8185 #if 0
8186         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8187         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8188         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8189         r_refdef.view.frustum[0].dist = m[15] - m[12];
8190
8191         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8192         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8193         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8194         r_refdef.view.frustum[1].dist = m[15] + m[12];
8195
8196         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8197         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8198         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8199         r_refdef.view.frustum[2].dist = m[15] - m[13];
8200
8201         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8202         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8203         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8204         r_refdef.view.frustum[3].dist = m[15] + m[13];
8205
8206         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8207         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8208         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8209         r_refdef.view.frustum[4].dist = m[15] - m[14];
8210
8211         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8212         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8213         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8214         r_refdef.view.frustum[5].dist = m[15] + m[14];
8215 #endif
8216
8217         if (r_refdef.view.useperspective)
8218         {
8219                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8220                 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]);
8221                 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]);
8222                 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]);
8223                 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]);
8224
8225                 // then the normals from the corners relative to origin
8226                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8227                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8228                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8229                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8230
8231                 // in a NORMAL view, forward cross left == up
8232                 // in a REFLECTED view, forward cross left == down
8233                 // so our cross products above need to be adjusted for a left handed coordinate system
8234                 CrossProduct(forward, left, v);
8235                 if(DotProduct(v, up) < 0)
8236                 {
8237                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8238                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8239                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8240                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8241                 }
8242
8243                 // Leaving those out was a mistake, those were in the old code, and they
8244                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8245                 // I couldn't reproduce it after adding those normalizations. --blub
8246                 VectorNormalize(r_refdef.view.frustum[0].normal);
8247                 VectorNormalize(r_refdef.view.frustum[1].normal);
8248                 VectorNormalize(r_refdef.view.frustum[2].normal);
8249                 VectorNormalize(r_refdef.view.frustum[3].normal);
8250
8251                 // make the corners absolute
8252                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8253                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8254                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8255                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8256
8257                 // one more normal
8258                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8259
8260                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8261                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8262                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8263                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8264                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8265         }
8266         else
8267         {
8268                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8269                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8270                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8271                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8272                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8273                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8274                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8275                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8276                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8277                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8278         }
8279         r_refdef.view.numfrustumplanes = 5;
8280
8281         if (r_refdef.view.useclipplane)
8282         {
8283                 r_refdef.view.numfrustumplanes = 6;
8284                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8285         }
8286
8287         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8288                 PlaneClassify(r_refdef.view.frustum + i);
8289
8290         // LordHavoc: note to all quake engine coders, Quake had a special case
8291         // for 90 degrees which assumed a square view (wrong), so I removed it,
8292         // Quake2 has it disabled as well.
8293
8294         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8295         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8296         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8297         //PlaneClassify(&frustum[0]);
8298
8299         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8300         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8301         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8302         //PlaneClassify(&frustum[1]);
8303
8304         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8305         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8306         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8307         //PlaneClassify(&frustum[2]);
8308
8309         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8310         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8311         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8312         //PlaneClassify(&frustum[3]);
8313
8314         // nearclip plane
8315         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8316         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8317         //PlaneClassify(&frustum[4]);
8318 }
8319
8320 void R_View_UpdateWithScissor(const int *myscissor)
8321 {
8322         R_Main_ResizeViewCache();
8323         R_View_SetFrustum(myscissor);
8324         R_View_WorldVisibility(r_refdef.view.useclipplane);
8325         R_View_UpdateEntityVisible();
8326         R_View_UpdateEntityLighting();
8327 }
8328
8329 void R_View_Update(void)
8330 {
8331         R_Main_ResizeViewCache();
8332         R_View_SetFrustum(NULL);
8333         R_View_WorldVisibility(r_refdef.view.useclipplane);
8334         R_View_UpdateEntityVisible();
8335         R_View_UpdateEntityLighting();
8336 }
8337
8338 void R_SetupView(qboolean allowwaterclippingplane)
8339 {
8340         const float *customclipplane = NULL;
8341         float plane[4];
8342         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8343         {
8344                 // LordHavoc: couldn't figure out how to make this approach the
8345                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8346                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8347                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8348                         dist = r_refdef.view.clipplane.dist;
8349                 plane[0] = r_refdef.view.clipplane.normal[0];
8350                 plane[1] = r_refdef.view.clipplane.normal[1];
8351                 plane[2] = r_refdef.view.clipplane.normal[2];
8352                 plane[3] = dist;
8353                 customclipplane = plane;
8354         }
8355
8356         if (!r_refdef.view.useperspective)
8357                 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);
8358         else if (vid.stencil && r_useinfinitefarclip.integer)
8359                 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);
8360         else
8361                 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);
8362         R_SetViewport(&r_refdef.view.viewport);
8363 }
8364
8365 void R_EntityMatrix(const matrix4x4_t *matrix)
8366 {
8367         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8368         {
8369                 gl_modelmatrixchanged = false;
8370                 gl_modelmatrix = *matrix;
8371                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8372                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8373                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8374                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8375                 CHECKGLERROR
8376                 switch(vid.renderpath)
8377                 {
8378                 case RENDERPATH_D3D9:
8379 #ifdef SUPPORTD3D
8380                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8381                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8382 #endif
8383                         break;
8384                 case RENDERPATH_D3D10:
8385                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8386                         break;
8387                 case RENDERPATH_D3D11:
8388                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8389                         break;
8390                 case RENDERPATH_GL20:
8391                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8392                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8393                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8394                         break;
8395                 case RENDERPATH_CGGL:
8396 #ifdef SUPPORTCG
8397                         CHECKCGERROR
8398                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8399                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8400                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8401 #endif
8402                         break;
8403                 case RENDERPATH_GL13:
8404                 case RENDERPATH_GL11:
8405                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8406                         break;
8407                 }
8408         }
8409 }
8410
8411 void R_ResetViewRendering2D(void)
8412 {
8413         r_viewport_t viewport;
8414         DrawQ_Finish();
8415
8416         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8417         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);
8418         R_SetViewport(&viewport);
8419         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8420         GL_Color(1, 1, 1, 1);
8421         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8422         GL_BlendFunc(GL_ONE, GL_ZERO);
8423         GL_AlphaTest(false);
8424         GL_ScissorTest(false);
8425         GL_DepthMask(false);
8426         GL_DepthRange(0, 1);
8427         GL_DepthTest(false);
8428         GL_DepthFunc(GL_LEQUAL);
8429         R_EntityMatrix(&identitymatrix);
8430         R_Mesh_ResetTextureState();
8431         GL_PolygonOffset(0, 0);
8432         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8433         switch(vid.renderpath)
8434         {
8435         case RENDERPATH_GL11:
8436         case RENDERPATH_GL13:
8437         case RENDERPATH_GL20:
8438         case RENDERPATH_CGGL:
8439                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8440                 break;
8441         case RENDERPATH_D3D9:
8442         case RENDERPATH_D3D10:
8443         case RENDERPATH_D3D11:
8444                 break;
8445         }
8446         GL_CullFace(GL_NONE);
8447 }
8448
8449 void R_ResetViewRendering3D(void)
8450 {
8451         DrawQ_Finish();
8452
8453         R_SetupView(true);
8454         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8455         GL_Color(1, 1, 1, 1);
8456         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8457         GL_BlendFunc(GL_ONE, GL_ZERO);
8458         GL_AlphaTest(false);
8459         GL_ScissorTest(true);
8460         GL_DepthMask(true);
8461         GL_DepthRange(0, 1);
8462         GL_DepthTest(true);
8463         GL_DepthFunc(GL_LEQUAL);
8464         R_EntityMatrix(&identitymatrix);
8465         R_Mesh_ResetTextureState();
8466         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8467         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8468         switch(vid.renderpath)
8469         {
8470         case RENDERPATH_GL11:
8471         case RENDERPATH_GL13:
8472         case RENDERPATH_GL20:
8473         case RENDERPATH_CGGL:
8474                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8475                 break;
8476         case RENDERPATH_D3D9:
8477         case RENDERPATH_D3D10:
8478         case RENDERPATH_D3D11:
8479                 break;
8480         }
8481         GL_CullFace(r_refdef.view.cullface_back);
8482 }
8483
8484 /*
8485 ================
8486 R_RenderView_UpdateViewVectors
8487 ================
8488 */
8489 static void R_RenderView_UpdateViewVectors(void)
8490 {
8491         // break apart the view matrix into vectors for various purposes
8492         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8493         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8494         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8495         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8496         // make an inverted copy of the view matrix for tracking sprites
8497         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8498 }
8499
8500 void R_RenderScene(void);
8501 void R_RenderWaterPlanes(void);
8502
8503 static void R_Water_StartFrame(void)
8504 {
8505         int i;
8506         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8507         r_waterstate_waterplane_t *p;
8508
8509         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8510                 return;
8511
8512         switch(vid.renderpath)
8513         {
8514         case RENDERPATH_GL20:
8515         case RENDERPATH_CGGL:
8516         case RENDERPATH_D3D9:
8517         case RENDERPATH_D3D10:
8518         case RENDERPATH_D3D11:
8519                 break;
8520         case RENDERPATH_GL13:
8521         case RENDERPATH_GL11:
8522                 return;
8523         }
8524
8525         // set waterwidth and waterheight to the water resolution that will be
8526         // used (often less than the screen resolution for faster rendering)
8527         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8528         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8529
8530         // calculate desired texture sizes
8531         // can't use water if the card does not support the texture size
8532         if (!r_water.integer || r_showsurfaces.integer)
8533                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8534         else if (vid.support.arb_texture_non_power_of_two)
8535         {
8536                 texturewidth = waterwidth;
8537                 textureheight = waterheight;
8538                 camerawidth = waterwidth;
8539                 cameraheight = waterheight;
8540         }
8541         else
8542         {
8543                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8544                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8545                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8546                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8547         }
8548
8549         // allocate textures as needed
8550         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8551         {
8552                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8553                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8554                 {
8555                         if (p->texture_refraction)
8556                                 R_FreeTexture(p->texture_refraction);
8557                         p->texture_refraction = NULL;
8558                         if (p->texture_reflection)
8559                                 R_FreeTexture(p->texture_reflection);
8560                         p->texture_reflection = NULL;
8561                         if (p->texture_camera)
8562                                 R_FreeTexture(p->texture_camera);
8563                         p->texture_camera = NULL;
8564                 }
8565                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8566                 r_waterstate.texturewidth = texturewidth;
8567                 r_waterstate.textureheight = textureheight;
8568                 r_waterstate.camerawidth = camerawidth;
8569                 r_waterstate.cameraheight = cameraheight;
8570         }
8571
8572         if (r_waterstate.texturewidth)
8573         {
8574                 r_waterstate.enabled = true;
8575
8576                 // when doing a reduced render (HDR) we want to use a smaller area
8577                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8578                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8579
8580                 // set up variables that will be used in shader setup
8581                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8582                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8583                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8584                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8585         }
8586
8587         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8588         r_waterstate.numwaterplanes = 0;
8589 }
8590
8591 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8592 {
8593         int triangleindex, planeindex;
8594         const int *e;
8595         vec3_t vert[3];
8596         vec3_t normal;
8597         vec3_t center;
8598         mplane_t plane;
8599         r_waterstate_waterplane_t *p;
8600         texture_t *t = R_GetCurrentTexture(surface->texture);
8601
8602         // just use the first triangle with a valid normal for any decisions
8603         VectorClear(normal);
8604         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8605         {
8606                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8607                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8608                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8609                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8610                 if (VectorLength2(normal) >= 0.001)
8611                         break;
8612         }
8613
8614         VectorCopy(normal, plane.normal);
8615         VectorNormalize(plane.normal);
8616         plane.dist = DotProduct(vert[0], plane.normal);
8617         PlaneClassify(&plane);
8618         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8619         {
8620                 // skip backfaces (except if nocullface is set)
8621                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8622                         return;
8623                 VectorNegate(plane.normal, plane.normal);
8624                 plane.dist *= -1;
8625                 PlaneClassify(&plane);
8626         }
8627
8628
8629         // find a matching plane if there is one
8630         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8631                 if(p->camera_entity == t->camera_entity)
8632                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8633                                 break;
8634         if (planeindex >= r_waterstate.maxwaterplanes)
8635                 return; // nothing we can do, out of planes
8636
8637         // if this triangle does not fit any known plane rendered this frame, add one
8638         if (planeindex >= r_waterstate.numwaterplanes)
8639         {
8640                 // store the new plane
8641                 r_waterstate.numwaterplanes++;
8642                 p->plane = plane;
8643                 // clear materialflags and pvs
8644                 p->materialflags = 0;
8645                 p->pvsvalid = false;
8646                 p->camera_entity = t->camera_entity;
8647                 VectorCopy(surface->mins, p->mins);
8648                 VectorCopy(surface->maxs, p->maxs);
8649         }
8650         else
8651         {
8652                 // merge mins/maxs
8653                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8654                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8655                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8656                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8657                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8658                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8659         }
8660         // merge this surface's materialflags into the waterplane
8661         p->materialflags |= t->currentmaterialflags;
8662         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8663         {
8664                 // merge this surface's PVS into the waterplane
8665                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8666                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8667                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8668                 {
8669                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8670                         p->pvsvalid = true;
8671                 }
8672         }
8673 }
8674
8675 static void R_Water_ProcessPlanes(void)
8676 {
8677         int myscissor[4];
8678         r_refdef_view_t originalview;
8679         r_refdef_view_t myview;
8680         int planeindex;
8681         r_waterstate_waterplane_t *p;
8682         vec3_t visorigin;
8683
8684         originalview = r_refdef.view;
8685
8686         // make sure enough textures are allocated
8687         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8688         {
8689                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8690                 {
8691                         if (!p->texture_refraction)
8692                                 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);
8693                         if (!p->texture_refraction)
8694                                 goto error;
8695                 }
8696                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8697                 {
8698                         if (!p->texture_camera)
8699                                 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);
8700                         if (!p->texture_camera)
8701                                 goto error;
8702                 }
8703
8704                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8705                 {
8706                         if (!p->texture_reflection)
8707                                 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);
8708                         if (!p->texture_reflection)
8709                                 goto error;
8710                 }
8711         }
8712
8713         // render views
8714         r_refdef.view = originalview;
8715         r_refdef.view.showdebug = false;
8716         r_refdef.view.width = r_waterstate.waterwidth;
8717         r_refdef.view.height = r_waterstate.waterheight;
8718         r_refdef.view.useclipplane = true;
8719         myview = r_refdef.view;
8720         r_waterstate.renderingscene = true;
8721         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8722         {
8723                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8724                 {
8725                         r_refdef.view = myview;
8726                         if(r_water_scissormode.integer)
8727                         {
8728                                 R_SetupView(true);
8729                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8730                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8731                         }
8732
8733                         // render reflected scene and copy into texture
8734                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8735                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8736                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8737                         r_refdef.view.clipplane = p->plane;
8738
8739                         // reverse the cullface settings for this render
8740                         r_refdef.view.cullface_front = GL_FRONT;
8741                         r_refdef.view.cullface_back = GL_BACK;
8742                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8743                         {
8744                                 r_refdef.view.usecustompvs = true;
8745                                 if (p->pvsvalid)
8746                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8747                                 else
8748                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8749                         }
8750
8751                         R_ResetViewRendering3D();
8752                         R_ClearScreen(r_refdef.fogenabled);
8753                         if(r_water_scissormode.integer & 2)
8754                                 R_View_UpdateWithScissor(myscissor);
8755                         else
8756                                 R_View_Update();
8757                         if(r_water_scissormode.integer & 1)
8758                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8759                         R_RenderScene();
8760
8761                         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);
8762                 }
8763
8764                 // render the normal view scene and copy into texture
8765                 // (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)
8766                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8767                 {
8768                         r_refdef.view = myview;
8769                         if(r_water_scissormode.integer)
8770                         {
8771                                 R_SetupView(true);
8772                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8773                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8774                         }
8775
8776                         r_waterstate.renderingrefraction = true;
8777
8778                         r_refdef.view.clipplane = p->plane;
8779                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8780                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8781
8782                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8783                         {
8784                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8785                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8786                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8787                                 R_RenderView_UpdateViewVectors();
8788                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8789                                 {
8790                                         r_refdef.view.usecustompvs = true;
8791                                         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);
8792                                 }
8793                         }
8794
8795                         PlaneClassify(&r_refdef.view.clipplane);
8796
8797                         R_ResetViewRendering3D();
8798                         R_ClearScreen(r_refdef.fogenabled);
8799                         if(r_water_scissormode.integer & 2)
8800                                 R_View_UpdateWithScissor(myscissor);
8801                         else
8802                                 R_View_Update();
8803                         if(r_water_scissormode.integer & 1)
8804                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8805                         R_RenderScene();
8806
8807                         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);
8808                         r_waterstate.renderingrefraction = false;
8809                 }
8810                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8811                 {
8812                         r_refdef.view = myview;
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                         r_refdef.view.width = r_waterstate.camerawidth;
8819                         r_refdef.view.height = r_waterstate.cameraheight;
8820                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8821                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8822
8823                         if(p->camera_entity)
8824                         {
8825                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8826                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8827                         }
8828
8829                         // note: all of the view is used for displaying... so
8830                         // there is no use in scissoring
8831
8832                         // reverse the cullface settings for this render
8833                         r_refdef.view.cullface_front = GL_FRONT;
8834                         r_refdef.view.cullface_back = GL_BACK;
8835                         // also reverse the view matrix
8836                         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
8837                         R_RenderView_UpdateViewVectors();
8838                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8839                         {
8840                                 r_refdef.view.usecustompvs = true;
8841                                 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);
8842                         }
8843                         
8844                         // camera needs no clipplane
8845                         r_refdef.view.useclipplane = false;
8846
8847                         PlaneClassify(&r_refdef.view.clipplane);
8848
8849                         R_ResetViewRendering3D();
8850                         R_ClearScreen(r_refdef.fogenabled);
8851                         R_View_Update();
8852                         R_RenderScene();
8853
8854                         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);
8855                         r_waterstate.renderingrefraction = false;
8856                 }
8857
8858         }
8859         r_waterstate.renderingscene = false;
8860         r_refdef.view = originalview;
8861         R_ResetViewRendering3D();
8862         R_ClearScreen(r_refdef.fogenabled);
8863         R_View_Update();
8864         return;
8865 error:
8866         r_refdef.view = originalview;
8867         r_waterstate.renderingscene = false;
8868         Cvar_SetValueQuick(&r_water, 0);
8869         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8870         return;
8871 }
8872
8873 void R_Bloom_StartFrame(void)
8874 {
8875         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8876
8877         switch(vid.renderpath)
8878         {
8879         case RENDERPATH_GL20:
8880         case RENDERPATH_CGGL:
8881         case RENDERPATH_D3D9:
8882         case RENDERPATH_D3D10:
8883         case RENDERPATH_D3D11:
8884                 break;
8885         case RENDERPATH_GL13:
8886         case RENDERPATH_GL11:
8887                 return;
8888         }
8889
8890         // set bloomwidth and bloomheight to the bloom resolution that will be
8891         // used (often less than the screen resolution for faster rendering)
8892         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8893         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8894         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8895         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8896         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8897
8898         // calculate desired texture sizes
8899         if (vid.support.arb_texture_non_power_of_two)
8900         {
8901                 screentexturewidth = r_refdef.view.width;
8902                 screentextureheight = r_refdef.view.height;
8903                 bloomtexturewidth = r_bloomstate.bloomwidth;
8904                 bloomtextureheight = r_bloomstate.bloomheight;
8905         }
8906         else
8907         {
8908                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8909                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8910                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8911                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8912         }
8913
8914         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))
8915         {
8916                 Cvar_SetValueQuick(&r_hdr, 0);
8917                 Cvar_SetValueQuick(&r_bloom, 0);
8918                 Cvar_SetValueQuick(&r_motionblur, 0);
8919                 Cvar_SetValueQuick(&r_damageblur, 0);
8920         }
8921
8922         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)))
8923                 screentexturewidth = screentextureheight = 0;
8924         if (!r_hdr.integer && !r_bloom.integer)
8925                 bloomtexturewidth = bloomtextureheight = 0;
8926
8927         // allocate textures as needed
8928         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8929         {
8930                 if (r_bloomstate.texture_screen)
8931                         R_FreeTexture(r_bloomstate.texture_screen);
8932                 r_bloomstate.texture_screen = NULL;
8933                 r_bloomstate.screentexturewidth = screentexturewidth;
8934                 r_bloomstate.screentextureheight = screentextureheight;
8935                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8936                         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);
8937         }
8938         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8939         {
8940                 if (r_bloomstate.texture_bloom)
8941                         R_FreeTexture(r_bloomstate.texture_bloom);
8942                 r_bloomstate.texture_bloom = NULL;
8943                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8944                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8945                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8946                         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);
8947         }
8948
8949         // when doing a reduced render (HDR) we want to use a smaller area
8950         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8951         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8952         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8953         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8954         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8955
8956         // set up a texcoord array for the full resolution screen image
8957         // (we have to keep this around to copy back during final render)
8958         r_bloomstate.screentexcoord2f[0] = 0;
8959         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8960         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8961         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8962         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8963         r_bloomstate.screentexcoord2f[5] = 0;
8964         r_bloomstate.screentexcoord2f[6] = 0;
8965         r_bloomstate.screentexcoord2f[7] = 0;
8966
8967         // set up a texcoord array for the reduced resolution bloom image
8968         // (which will be additive blended over the screen image)
8969         r_bloomstate.bloomtexcoord2f[0] = 0;
8970         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8971         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8972         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8973         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8974         r_bloomstate.bloomtexcoord2f[5] = 0;
8975         r_bloomstate.bloomtexcoord2f[6] = 0;
8976         r_bloomstate.bloomtexcoord2f[7] = 0;
8977
8978         switch(vid.renderpath)
8979         {
8980         case RENDERPATH_GL11:
8981         case RENDERPATH_GL13:
8982         case RENDERPATH_GL20:
8983         case RENDERPATH_CGGL:
8984                 break;
8985         case RENDERPATH_D3D9:
8986         case RENDERPATH_D3D10:
8987         case RENDERPATH_D3D11:
8988                 {
8989                         int i;
8990                         for (i = 0;i < 4;i++)
8991                         {
8992                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8993                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8994                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8995                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8996                         }
8997                 }
8998                 break;
8999         }
9000
9001         if (r_hdr.integer || r_bloom.integer)
9002         {
9003                 r_bloomstate.enabled = true;
9004                 r_bloomstate.hdr = r_hdr.integer != 0;
9005         }
9006
9007         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);
9008 }
9009
9010 void R_Bloom_CopyBloomTexture(float colorscale)
9011 {
9012         r_refdef.stats.bloom++;
9013
9014         // scale down screen texture to the bloom texture size
9015         CHECKGLERROR
9016         R_SetViewport(&r_bloomstate.viewport);
9017         GL_BlendFunc(GL_ONE, GL_ZERO);
9018         GL_Color(colorscale, colorscale, colorscale, 1);
9019         // 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...
9020         switch(vid.renderpath)
9021         {
9022         case RENDERPATH_GL11:
9023         case RENDERPATH_GL13:
9024         case RENDERPATH_GL20:
9025         case RENDERPATH_CGGL:
9026                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9027                 break;
9028         case RENDERPATH_D3D9:
9029         case RENDERPATH_D3D10:
9030         case RENDERPATH_D3D11:
9031                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9032                 break;
9033         }
9034         // TODO: do boxfilter scale-down in shader?
9035         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9036         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9037         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9038
9039         // we now have a bloom image in the framebuffer
9040         // copy it into the bloom image texture for later processing
9041         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);
9042         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9043 }
9044
9045 void R_Bloom_CopyHDRTexture(void)
9046 {
9047         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);
9048         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9049 }
9050
9051 void R_Bloom_MakeTexture(void)
9052 {
9053         int x, range, dir;
9054         float xoffset, yoffset, r, brighten;
9055
9056         r_refdef.stats.bloom++;
9057
9058         R_ResetViewRendering2D();
9059
9060         // we have a bloom image in the framebuffer
9061         CHECKGLERROR
9062         R_SetViewport(&r_bloomstate.viewport);
9063
9064         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9065         {
9066                 x *= 2;
9067                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9068                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9069                 GL_Color(r,r,r,1);
9070                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9071                 R_SetupShader_Generic(r_bloomstate.texture_bloom, 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                 // copy the vertically blurred bloom view to a texture
9076                 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);
9077                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9078         }
9079
9080         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9081         brighten = r_bloom_brighten.value;
9082         if (r_hdr.integer)
9083                 brighten *= r_hdr_range.value;
9084         brighten = sqrt(brighten);
9085         if(range >= 1)
9086                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9087         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9088
9089         for (dir = 0;dir < 2;dir++)
9090         {
9091                 // blend on at multiple vertical offsets to achieve a vertical blur
9092                 // TODO: do offset blends using GLSL
9093                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9094                 GL_BlendFunc(GL_ONE, GL_ZERO);
9095                 for (x = -range;x <= range;x++)
9096                 {
9097                         if (!dir){xoffset = 0;yoffset = x;}
9098                         else {xoffset = x;yoffset = 0;}
9099                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9100                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9101                         // compute a texcoord array with the specified x and y offset
9102                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9103                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9104                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9105                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9106                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9107                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9108                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9109                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9110                         // this r value looks like a 'dot' particle, fading sharply to
9111                         // black at the edges
9112                         // (probably not realistic but looks good enough)
9113                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9114                         //r = brighten/(range*2+1);
9115                         r = brighten / (range * 2 + 1);
9116                         if(range >= 1)
9117                                 r *= (1 - x*x/(float)(range*range));
9118                         GL_Color(r, r, r, 1);
9119                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9120                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9121                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9122                         GL_BlendFunc(GL_ONE, GL_ONE);
9123                 }
9124
9125                 // copy the vertically blurred bloom view to a texture
9126                 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);
9127                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9128         }
9129 }
9130
9131 void R_HDR_RenderBloomTexture(void)
9132 {
9133         int oldwidth, oldheight;
9134         float oldcolorscale;
9135
9136         oldcolorscale = r_refdef.view.colorscale;
9137         oldwidth = r_refdef.view.width;
9138         oldheight = r_refdef.view.height;
9139         r_refdef.view.width = r_bloomstate.bloomwidth;
9140         r_refdef.view.height = r_bloomstate.bloomheight;
9141
9142         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9143         // TODO: add exposure compensation features
9144         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9145
9146         r_refdef.view.showdebug = false;
9147         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9148
9149         R_ResetViewRendering3D();
9150
9151         R_ClearScreen(r_refdef.fogenabled);
9152         if (r_timereport_active)
9153                 R_TimeReport("HDRclear");
9154
9155         R_View_Update();
9156         if (r_timereport_active)
9157                 R_TimeReport("visibility");
9158
9159         // only do secondary renders with HDR if r_hdr is 2 or higher
9160         r_waterstate.numwaterplanes = 0;
9161         if (r_waterstate.enabled && r_hdr.integer >= 2)
9162                 R_RenderWaterPlanes();
9163
9164         r_refdef.view.showdebug = true;
9165         R_RenderScene();
9166         r_waterstate.numwaterplanes = 0;
9167
9168         R_ResetViewRendering2D();
9169
9170         R_Bloom_CopyHDRTexture();
9171         R_Bloom_MakeTexture();
9172
9173         // restore the view settings
9174         r_refdef.view.width = oldwidth;
9175         r_refdef.view.height = oldheight;
9176         r_refdef.view.colorscale = oldcolorscale;
9177
9178         R_ResetViewRendering3D();
9179
9180         R_ClearScreen(r_refdef.fogenabled);
9181         if (r_timereport_active)
9182                 R_TimeReport("viewclear");
9183 }
9184
9185 static void R_BlendView(void)
9186 {
9187         unsigned int permutation;
9188         float uservecs[4][4];
9189
9190         switch (vid.renderpath)
9191         {
9192         case RENDERPATH_GL20:
9193         case RENDERPATH_CGGL:
9194         case RENDERPATH_D3D9:
9195         case RENDERPATH_D3D10:
9196         case RENDERPATH_D3D11:
9197                 permutation =
9198                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9199                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9200                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9201                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9202                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9203
9204                 if (r_bloomstate.texture_screen)
9205                 {
9206                         // make sure the buffer is available
9207                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9208
9209                         R_ResetViewRendering2D();
9210
9211                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9212                         {
9213                                 // declare variables
9214                                 float speed;
9215                                 static float avgspeed;
9216
9217                                 speed = VectorLength(cl.movement_velocity);
9218
9219                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9220                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9221
9222                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9223                                 speed = bound(0, speed, 1);
9224                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9225
9226                                 // calculate values into a standard alpha
9227                                 cl.motionbluralpha = 1 - exp(-
9228                                                 (
9229                                                  (r_motionblur.value * speed / 80)
9230                                                  +
9231                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9232                                                 )
9233                                                 /
9234                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9235                                            );
9236
9237                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9238                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9239                                 // apply the blur
9240                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9241                                 {
9242                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9243                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9244                                         switch(vid.renderpath)
9245                                         {
9246                                         case RENDERPATH_GL11:
9247                                         case RENDERPATH_GL13:
9248                                         case RENDERPATH_GL20:
9249                                         case RENDERPATH_CGGL:
9250                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9251                                                 break;
9252                                         case RENDERPATH_D3D9:
9253                                         case RENDERPATH_D3D10:
9254                                         case RENDERPATH_D3D11:
9255                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9256                                                 break;
9257                                         }
9258                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9259                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9260                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9261                                 }
9262                         }
9263
9264                         // copy view into the screen texture
9265                         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);
9266                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9267                 }
9268                 else if (!r_bloomstate.texture_bloom)
9269                 {
9270                         // we may still have to do view tint...
9271                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9272                         {
9273                                 // apply a color tint to the whole view
9274                                 R_ResetViewRendering2D();
9275                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9276                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9277                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9278                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9279                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9280                         }
9281                         break; // no screen processing, no bloom, skip it
9282                 }
9283
9284                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9285                 {
9286                         // render simple bloom effect
9287                         // copy the screen and shrink it and darken it for the bloom process
9288                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9289                         // make the bloom texture
9290                         R_Bloom_MakeTexture();
9291                 }
9292
9293 #if _MSC_VER >= 1400
9294 #define sscanf sscanf_s
9295 #endif
9296                 memset(uservecs, 0, sizeof(uservecs));
9297                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9298                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9299                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9300                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9301
9302                 R_ResetViewRendering2D();
9303                 GL_Color(1, 1, 1, 1);
9304                 GL_BlendFunc(GL_ONE, GL_ZERO);
9305
9306                 switch(vid.renderpath)
9307                 {
9308                 case RENDERPATH_GL20:
9309                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9310                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9311                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9312                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9313                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9314                         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]);
9315                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9316                         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]);
9317                         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]);
9318                         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]);
9319                         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]);
9320                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9321                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9322                         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);
9323                         break;
9324                 case RENDERPATH_CGGL:
9325 #ifdef SUPPORTCG
9326                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9327                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9328                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9329                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9330                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9331                         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
9332                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9333                         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
9334                         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
9335                         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
9336                         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
9337                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9338                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9339                         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);
9340 #endif
9341                         break;
9342                 case RENDERPATH_D3D9:
9343 #ifdef SUPPORTD3D
9344                         // 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...
9345                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9346                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9347                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9348                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9349                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9350                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9351                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9352                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9353                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9354                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9355                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9356                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9357                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9358                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9359 #endif
9360                         break;
9361                 case RENDERPATH_D3D10:
9362                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9363                         break;
9364                 case RENDERPATH_D3D11:
9365                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9366                         break;
9367                 default:
9368                         break;
9369                 }
9370                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9371                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9372                 break;
9373         case RENDERPATH_GL13:
9374         case RENDERPATH_GL11:
9375                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9376                 {
9377                         // apply a color tint to the whole view
9378                         R_ResetViewRendering2D();
9379                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9380                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9381                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9382                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9383                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9384                 }
9385                 break;
9386         }
9387 }
9388
9389 matrix4x4_t r_waterscrollmatrix;
9390
9391 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9392 {
9393         if (r_refdef.fog_density)
9394         {
9395                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9396                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9397                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9398
9399                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9400                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9401                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9402                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9403
9404                 {
9405                         vec3_t fogvec;
9406                         VectorCopy(r_refdef.fogcolor, fogvec);
9407                         //   color.rgb *= ContrastBoost * SceneBrightness;
9408                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9409                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9410                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9411                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9412                 }
9413         }
9414 }
9415
9416 void R_UpdateVariables(void)
9417 {
9418         R_Textures_Frame();
9419
9420         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9421
9422         r_refdef.farclip = r_farclip_base.value;
9423         if (r_refdef.scene.worldmodel)
9424                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9425         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9426
9427         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9428                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9429         r_refdef.polygonfactor = 0;
9430         r_refdef.polygonoffset = 0;
9431         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9432         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9433
9434         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9435         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9436         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9437         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9438         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9439         if (FAKELIGHT_ENABLED)
9440         {
9441                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9442         }
9443         if (r_showsurfaces.integer)
9444         {
9445                 r_refdef.scene.rtworld = false;
9446                 r_refdef.scene.rtworldshadows = false;
9447                 r_refdef.scene.rtdlight = false;
9448                 r_refdef.scene.rtdlightshadows = false;
9449                 r_refdef.lightmapintensity = 0;
9450         }
9451
9452         if (gamemode == GAME_NEHAHRA)
9453         {
9454                 if (gl_fogenable.integer)
9455                 {
9456                         r_refdef.oldgl_fogenable = true;
9457                         r_refdef.fog_density = gl_fogdensity.value;
9458                         r_refdef.fog_red = gl_fogred.value;
9459                         r_refdef.fog_green = gl_foggreen.value;
9460                         r_refdef.fog_blue = gl_fogblue.value;
9461                         r_refdef.fog_alpha = 1;
9462                         r_refdef.fog_start = 0;
9463                         r_refdef.fog_end = gl_skyclip.value;
9464                         r_refdef.fog_height = 1<<30;
9465                         r_refdef.fog_fadedepth = 128;
9466                 }
9467                 else if (r_refdef.oldgl_fogenable)
9468                 {
9469                         r_refdef.oldgl_fogenable = false;
9470                         r_refdef.fog_density = 0;
9471                         r_refdef.fog_red = 0;
9472                         r_refdef.fog_green = 0;
9473                         r_refdef.fog_blue = 0;
9474                         r_refdef.fog_alpha = 0;
9475                         r_refdef.fog_start = 0;
9476                         r_refdef.fog_end = 0;
9477                         r_refdef.fog_height = 1<<30;
9478                         r_refdef.fog_fadedepth = 128;
9479                 }
9480         }
9481
9482         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9483         r_refdef.fog_start = max(0, r_refdef.fog_start);
9484         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9485
9486         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9487
9488         if (r_refdef.fog_density && r_drawfog.integer)
9489         {
9490                 r_refdef.fogenabled = true;
9491                 // this is the point where the fog reaches 0.9986 alpha, which we
9492                 // consider a good enough cutoff point for the texture
9493                 // (0.9986 * 256 == 255.6)
9494                 if (r_fog_exp2.integer)
9495                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9496                 else
9497                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9498                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9499                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9500                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9501                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9502                         R_BuildFogHeightTexture();
9503                 // fog color was already set
9504                 // update the fog texture
9505                 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)
9506                         R_BuildFogTexture();
9507                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9508                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9509         }
9510         else
9511                 r_refdef.fogenabled = false;
9512
9513         switch(vid.renderpath)
9514         {
9515         case RENDERPATH_GL20:
9516         case RENDERPATH_CGGL:
9517         case RENDERPATH_D3D9:
9518         case RENDERPATH_D3D10:
9519         case RENDERPATH_D3D11:
9520                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9521                 {
9522                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9523                         {
9524                                 // build GLSL gamma texture
9525 #define RAMPWIDTH 256
9526                                 unsigned short ramp[RAMPWIDTH * 3];
9527                                 unsigned char rampbgr[RAMPWIDTH][4];
9528                                 int i;
9529
9530                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9531
9532                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9533                                 for(i = 0; i < RAMPWIDTH; ++i)
9534                                 {
9535                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9536                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9537                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9538                                         rampbgr[i][3] = 0;
9539                                 }
9540                                 if (r_texture_gammaramps)
9541                                 {
9542                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9543                                 }
9544                                 else
9545                                 {
9546                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9547                                 }
9548                         }
9549                 }
9550                 else
9551                 {
9552                         // remove GLSL gamma texture
9553                 }
9554                 break;
9555         case RENDERPATH_GL13:
9556         case RENDERPATH_GL11:
9557                 break;
9558         }
9559 }
9560
9561 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9562 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9563 /*
9564 ================
9565 R_SelectScene
9566 ================
9567 */
9568 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9569         if( scenetype != r_currentscenetype ) {
9570                 // store the old scenetype
9571                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9572                 r_currentscenetype = scenetype;
9573                 // move in the new scene
9574                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9575         }
9576 }
9577
9578 /*
9579 ================
9580 R_GetScenePointer
9581 ================
9582 */
9583 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9584 {
9585         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9586         if( scenetype == r_currentscenetype ) {
9587                 return &r_refdef.scene;
9588         } else {
9589                 return &r_scenes_store[ scenetype ];
9590         }
9591 }
9592
9593 /*
9594 ================
9595 R_RenderView
9596 ================
9597 */
9598 void R_RenderView(void)
9599 {
9600         if (r_timereport_active)
9601                 R_TimeReport("start");
9602         r_textureframe++; // used only by R_GetCurrentTexture
9603         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9604
9605         if(R_CompileShader_CheckStaticParms())
9606                 R_GLSL_Restart_f();
9607
9608         if (!r_drawentities.integer)
9609                 r_refdef.scene.numentities = 0;
9610
9611         R_AnimCache_ClearCache();
9612         R_FrameData_NewFrame();
9613
9614         if (r_refdef.view.isoverlay)
9615         {
9616                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9617                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9618                 R_TimeReport("depthclear");
9619
9620                 r_refdef.view.showdebug = false;
9621
9622                 r_waterstate.enabled = false;
9623                 r_waterstate.numwaterplanes = 0;
9624
9625                 R_RenderScene();
9626
9627                 CHECKGLERROR
9628                 return;
9629         }
9630
9631         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9632                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9633
9634         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9635
9636         R_RenderView_UpdateViewVectors();
9637
9638         R_Shadow_UpdateWorldLightSelection();
9639
9640         R_Bloom_StartFrame();
9641         R_Water_StartFrame();
9642
9643         CHECKGLERROR
9644         if (r_timereport_active)
9645                 R_TimeReport("viewsetup");
9646
9647         R_ResetViewRendering3D();
9648
9649         if (r_refdef.view.clear || r_refdef.fogenabled)
9650         {
9651                 R_ClearScreen(r_refdef.fogenabled);
9652                 if (r_timereport_active)
9653                         R_TimeReport("viewclear");
9654         }
9655         r_refdef.view.clear = true;
9656
9657         // this produces a bloom texture to be used in R_BlendView() later
9658         if (r_hdr.integer && r_bloomstate.bloomwidth)
9659         {
9660                 R_HDR_RenderBloomTexture();
9661                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9662                 r_textureframe++; // used only by R_GetCurrentTexture
9663         }
9664
9665         r_refdef.view.showdebug = true;
9666
9667         R_View_Update();
9668         if (r_timereport_active)
9669                 R_TimeReport("visibility");
9670
9671         r_waterstate.numwaterplanes = 0;
9672         if (r_waterstate.enabled)
9673                 R_RenderWaterPlanes();
9674
9675         R_RenderScene();
9676         r_waterstate.numwaterplanes = 0;
9677
9678         R_BlendView();
9679         if (r_timereport_active)
9680                 R_TimeReport("blendview");
9681
9682         GL_Scissor(0, 0, vid.width, vid.height);
9683         GL_ScissorTest(false);
9684
9685         CHECKGLERROR
9686 }
9687
9688 void R_RenderWaterPlanes(void)
9689 {
9690         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9691         {
9692                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9693                 if (r_timereport_active)
9694                         R_TimeReport("waterworld");
9695         }
9696
9697         // don't let sound skip if going slow
9698         if (r_refdef.scene.extraupdate)
9699                 S_ExtraUpdate ();
9700
9701         R_DrawModelsAddWaterPlanes();
9702         if (r_timereport_active)
9703                 R_TimeReport("watermodels");
9704
9705         if (r_waterstate.numwaterplanes)
9706         {
9707                 R_Water_ProcessPlanes();
9708                 if (r_timereport_active)
9709                         R_TimeReport("waterscenes");
9710         }
9711 }
9712
9713 extern void R_DrawLightningBeams (void);
9714 extern void VM_CL_AddPolygonsToMeshQueue (void);
9715 extern void R_DrawPortals (void);
9716 extern cvar_t cl_locs_show;
9717 static void R_DrawLocs(void);
9718 static void R_DrawEntityBBoxes(void);
9719 static void R_DrawModelDecals(void);
9720 extern void R_DrawModelShadows(void);
9721 extern void R_DrawModelShadowMaps(void);
9722 extern cvar_t cl_decals_newsystem;
9723 extern qboolean r_shadow_usingdeferredprepass;
9724 void R_RenderScene(void)
9725 {
9726         qboolean shadowmapping = false;
9727
9728         if (r_timereport_active)
9729                 R_TimeReport("beginscene");
9730
9731         r_refdef.stats.renders++;
9732
9733         R_UpdateFogColor();
9734
9735         // don't let sound skip if going slow
9736         if (r_refdef.scene.extraupdate)
9737                 S_ExtraUpdate ();
9738
9739         R_MeshQueue_BeginScene();
9740
9741         R_SkyStartFrame();
9742
9743         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);
9744
9745         if (r_timereport_active)
9746                 R_TimeReport("skystartframe");
9747
9748         if (cl.csqc_vidvars.drawworld)
9749         {
9750                 // don't let sound skip if going slow
9751                 if (r_refdef.scene.extraupdate)
9752                         S_ExtraUpdate ();
9753
9754                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9755                 {
9756                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9757                         if (r_timereport_active)
9758                                 R_TimeReport("worldsky");
9759                 }
9760
9761                 if (R_DrawBrushModelsSky() && r_timereport_active)
9762                         R_TimeReport("bmodelsky");
9763
9764                 if (skyrendermasked && skyrenderlater)
9765                 {
9766                         // we have to force off the water clipping plane while rendering sky
9767                         R_SetupView(false);
9768                         R_Sky();
9769                         R_SetupView(true);
9770                         if (r_timereport_active)
9771                                 R_TimeReport("sky");
9772                 }
9773         }
9774
9775         R_AnimCache_CacheVisibleEntities();
9776         if (r_timereport_active)
9777                 R_TimeReport("animation");
9778
9779         R_Shadow_PrepareLights();
9780         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9781                 R_Shadow_PrepareModelShadows();
9782         if (r_timereport_active)
9783                 R_TimeReport("preparelights");
9784
9785         if (R_Shadow_ShadowMappingEnabled())
9786                 shadowmapping = true;
9787
9788         if (r_shadow_usingdeferredprepass)
9789                 R_Shadow_DrawPrepass();
9790
9791         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9792         {
9793                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9794                 if (r_timereport_active)
9795                         R_TimeReport("worlddepth");
9796         }
9797         if (r_depthfirst.integer >= 2)
9798         {
9799                 R_DrawModelsDepth();
9800                 if (r_timereport_active)
9801                         R_TimeReport("modeldepth");
9802         }
9803
9804         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9805         {
9806                 R_DrawModelShadowMaps();
9807                 R_ResetViewRendering3D();
9808                 // don't let sound skip if going slow
9809                 if (r_refdef.scene.extraupdate)
9810                         S_ExtraUpdate ();
9811         }
9812
9813         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9814         {
9815                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9816                 if (r_timereport_active)
9817                         R_TimeReport("world");
9818         }
9819
9820         // don't let sound skip if going slow
9821         if (r_refdef.scene.extraupdate)
9822                 S_ExtraUpdate ();
9823
9824         R_DrawModels();
9825         if (r_timereport_active)
9826                 R_TimeReport("models");
9827
9828         // don't let sound skip if going slow
9829         if (r_refdef.scene.extraupdate)
9830                 S_ExtraUpdate ();
9831
9832         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9833         {
9834                 R_DrawModelShadows();
9835                 R_ResetViewRendering3D();
9836                 // don't let sound skip if going slow
9837                 if (r_refdef.scene.extraupdate)
9838                         S_ExtraUpdate ();
9839         }
9840
9841         if (!r_shadow_usingdeferredprepass)
9842         {
9843                 R_Shadow_DrawLights();
9844                 if (r_timereport_active)
9845                         R_TimeReport("rtlights");
9846         }
9847
9848         // don't let sound skip if going slow
9849         if (r_refdef.scene.extraupdate)
9850                 S_ExtraUpdate ();
9851
9852         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9853         {
9854                 R_DrawModelShadows();
9855                 R_ResetViewRendering3D();
9856                 // don't let sound skip if going slow
9857                 if (r_refdef.scene.extraupdate)
9858                         S_ExtraUpdate ();
9859         }
9860
9861         if (cl.csqc_vidvars.drawworld)
9862         {
9863                 if (cl_decals_newsystem.integer)
9864                 {
9865                         R_DrawModelDecals();
9866                         if (r_timereport_active)
9867                                 R_TimeReport("modeldecals");
9868                 }
9869                 else
9870                 {
9871                         R_DrawDecals();
9872                         if (r_timereport_active)
9873                                 R_TimeReport("decals");
9874                 }
9875
9876                 R_DrawParticles();
9877                 if (r_timereport_active)
9878                         R_TimeReport("particles");
9879
9880                 R_DrawExplosions();
9881                 if (r_timereport_active)
9882                         R_TimeReport("explosions");
9883
9884                 R_DrawLightningBeams();
9885                 if (r_timereport_active)
9886                         R_TimeReport("lightning");
9887         }
9888
9889         VM_CL_AddPolygonsToMeshQueue();
9890
9891         if (r_refdef.view.showdebug)
9892         {
9893                 if (cl_locs_show.integer)
9894                 {
9895                         R_DrawLocs();
9896                         if (r_timereport_active)
9897                                 R_TimeReport("showlocs");
9898                 }
9899
9900                 if (r_drawportals.integer)
9901                 {
9902                         R_DrawPortals();
9903                         if (r_timereport_active)
9904                                 R_TimeReport("portals");
9905                 }
9906
9907                 if (r_showbboxes.value > 0)
9908                 {
9909                         R_DrawEntityBBoxes();
9910                         if (r_timereport_active)
9911                                 R_TimeReport("bboxes");
9912                 }
9913         }
9914
9915         R_MeshQueue_RenderTransparent();
9916         if (r_timereport_active)
9917                 R_TimeReport("drawtrans");
9918
9919         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))
9920         {
9921                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9922                 if (r_timereport_active)
9923                         R_TimeReport("worlddebug");
9924                 R_DrawModelsDebug();
9925                 if (r_timereport_active)
9926                         R_TimeReport("modeldebug");
9927         }
9928
9929         if (cl.csqc_vidvars.drawworld)
9930         {
9931                 R_Shadow_DrawCoronas();
9932                 if (r_timereport_active)
9933                         R_TimeReport("coronas");
9934         }
9935
9936 #if 0
9937         {
9938                 GL_DepthTest(false);
9939                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9940                 GL_Color(1, 1, 1, 1);
9941                 qglBegin(GL_POLYGON);
9942                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9943                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9944                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9945                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9946                 qglEnd();
9947                 qglBegin(GL_POLYGON);
9948                 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]);
9949                 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]);
9950                 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]);
9951                 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]);
9952                 qglEnd();
9953                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9954         }
9955 #endif
9956
9957         // don't let sound skip if going slow
9958         if (r_refdef.scene.extraupdate)
9959                 S_ExtraUpdate ();
9960
9961         R_ResetViewRendering2D();
9962 }
9963
9964 static const unsigned short bboxelements[36] =
9965 {
9966         5, 1, 3, 5, 3, 7,
9967         6, 2, 0, 6, 0, 4,
9968         7, 3, 2, 7, 2, 6,
9969         4, 0, 1, 4, 1, 5,
9970         4, 5, 7, 4, 7, 6,
9971         1, 0, 2, 1, 2, 3,
9972 };
9973
9974 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9975 {
9976         int i;
9977         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9978
9979         RSurf_ActiveWorldEntity();
9980
9981         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9982         GL_DepthMask(false);
9983         GL_DepthRange(0, 1);
9984         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9985         R_Mesh_ResetTextureState();
9986
9987         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9988         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9989         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9990         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9991         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9992         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9993         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9994         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9995         R_FillColors(color4f, 8, cr, cg, cb, ca);
9996         if (r_refdef.fogenabled)
9997         {
9998                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9999                 {
10000                         f1 = RSurf_FogVertex(v);
10001                         f2 = 1 - f1;
10002                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10003                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10004                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10005                 }
10006         }
10007         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10008         R_Mesh_ResetTextureState();
10009         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10010         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10011 }
10012
10013 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10014 {
10015         int i;
10016         float color[4];
10017         prvm_edict_t *edict;
10018         prvm_prog_t *prog_save = prog;
10019
10020         // this function draws bounding boxes of server entities
10021         if (!sv.active)
10022                 return;
10023
10024         GL_CullFace(GL_NONE);
10025         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10026
10027         prog = 0;
10028         SV_VM_Begin();
10029         for (i = 0;i < numsurfaces;i++)
10030         {
10031                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10032                 switch ((int)edict->fields.server->solid)
10033                 {
10034                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10035                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10036                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10037                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10038                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10039                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10040                 }
10041                 color[3] *= r_showbboxes.value;
10042                 color[3] = bound(0, color[3], 1);
10043                 GL_DepthTest(!r_showdisabledepthtest.integer);
10044                 GL_CullFace(r_refdef.view.cullface_front);
10045                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10046         }
10047         SV_VM_End();
10048         prog = prog_save;
10049 }
10050
10051 static void R_DrawEntityBBoxes(void)
10052 {
10053         int i;
10054         prvm_edict_t *edict;
10055         vec3_t center;
10056         prvm_prog_t *prog_save = prog;
10057
10058         // this function draws bounding boxes of server entities
10059         if (!sv.active)
10060                 return;
10061
10062         prog = 0;
10063         SV_VM_Begin();
10064         for (i = 0;i < prog->num_edicts;i++)
10065         {
10066                 edict = PRVM_EDICT_NUM(i);
10067                 if (edict->priv.server->free)
10068                         continue;
10069                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10070                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10071                         continue;
10072                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10073                         continue;
10074                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10075                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10076         }
10077         SV_VM_End();
10078         prog = prog_save;
10079 }
10080
10081 static const int nomodelelement3i[24] =
10082 {
10083         5, 2, 0,
10084         5, 1, 2,
10085         5, 0, 3,
10086         5, 3, 1,
10087         0, 2, 4,
10088         2, 1, 4,
10089         3, 0, 4,
10090         1, 3, 4
10091 };
10092
10093 static const unsigned short nomodelelement3s[24] =
10094 {
10095         5, 2, 0,
10096         5, 1, 2,
10097         5, 0, 3,
10098         5, 3, 1,
10099         0, 2, 4,
10100         2, 1, 4,
10101         3, 0, 4,
10102         1, 3, 4
10103 };
10104
10105 static const float nomodelvertex3f[6*3] =
10106 {
10107         -16,   0,   0,
10108          16,   0,   0,
10109           0, -16,   0,
10110           0,  16,   0,
10111           0,   0, -16,
10112           0,   0,  16
10113 };
10114
10115 static const float nomodelcolor4f[6*4] =
10116 {
10117         0.0f, 0.0f, 0.5f, 1.0f,
10118         0.0f, 0.0f, 0.5f, 1.0f,
10119         0.0f, 0.5f, 0.0f, 1.0f,
10120         0.0f, 0.5f, 0.0f, 1.0f,
10121         0.5f, 0.0f, 0.0f, 1.0f,
10122         0.5f, 0.0f, 0.0f, 1.0f
10123 };
10124
10125 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10126 {
10127         int i;
10128         float f1, f2, *c;
10129         float color4f[6*4];
10130
10131         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);
10132
10133         // this is only called once per entity so numsurfaces is always 1, and
10134         // surfacelist is always {0}, so this code does not handle batches
10135
10136         if (rsurface.ent_flags & RENDER_ADDITIVE)
10137         {
10138                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10139                 GL_DepthMask(false);
10140         }
10141         else if (rsurface.colormod[3] < 1)
10142         {
10143                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10144                 GL_DepthMask(false);
10145         }
10146         else
10147         {
10148                 GL_BlendFunc(GL_ONE, GL_ZERO);
10149                 GL_DepthMask(true);
10150         }
10151         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10152         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10153         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10154         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10155         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10156         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10157         for (i = 0, c = color4f;i < 6;i++, c += 4)
10158         {
10159                 c[0] *= rsurface.colormod[0];
10160                 c[1] *= rsurface.colormod[1];
10161                 c[2] *= rsurface.colormod[2];
10162                 c[3] *= rsurface.colormod[3];
10163         }
10164         if (r_refdef.fogenabled)
10165         {
10166                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10167                 {
10168                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10169                         f2 = 1 - f1;
10170                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10171                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10172                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10173                 }
10174         }
10175         R_Mesh_ResetTextureState();
10176         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10177         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10178 }
10179
10180 void R_DrawNoModel(entity_render_t *ent)
10181 {
10182         vec3_t org;
10183         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10184         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10185                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10186         else
10187                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10188 }
10189
10190 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10191 {
10192         vec3_t right1, right2, diff, normal;
10193
10194         VectorSubtract (org2, org1, normal);
10195
10196         // calculate 'right' vector for start
10197         VectorSubtract (r_refdef.view.origin, org1, diff);
10198         CrossProduct (normal, diff, right1);
10199         VectorNormalize (right1);
10200
10201         // calculate 'right' vector for end
10202         VectorSubtract (r_refdef.view.origin, org2, diff);
10203         CrossProduct (normal, diff, right2);
10204         VectorNormalize (right2);
10205
10206         vert[ 0] = org1[0] + width * right1[0];
10207         vert[ 1] = org1[1] + width * right1[1];
10208         vert[ 2] = org1[2] + width * right1[2];
10209         vert[ 3] = org1[0] - width * right1[0];
10210         vert[ 4] = org1[1] - width * right1[1];
10211         vert[ 5] = org1[2] - width * right1[2];
10212         vert[ 6] = org2[0] - width * right2[0];
10213         vert[ 7] = org2[1] - width * right2[1];
10214         vert[ 8] = org2[2] - width * right2[2];
10215         vert[ 9] = org2[0] + width * right2[0];
10216         vert[10] = org2[1] + width * right2[1];
10217         vert[11] = org2[2] + width * right2[2];
10218 }
10219
10220 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)
10221 {
10222         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10223         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10224         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10225         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10226         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10227         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10228         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10229         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10230         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10231         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10232         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10233         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10234 }
10235
10236 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10237 {
10238         int i;
10239         float *vertex3f;
10240         float v[3];
10241         VectorSet(v, x, y, z);
10242         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10243                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10244                         break;
10245         if (i == mesh->numvertices)
10246         {
10247                 if (mesh->numvertices < mesh->maxvertices)
10248                 {
10249                         VectorCopy(v, vertex3f);
10250                         mesh->numvertices++;
10251                 }
10252                 return mesh->numvertices;
10253         }
10254         else
10255                 return i;
10256 }
10257
10258 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10259 {
10260         int i;
10261         int *e, element[3];
10262         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10263         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10264         e = mesh->element3i + mesh->numtriangles * 3;
10265         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10266         {
10267                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10268                 if (mesh->numtriangles < mesh->maxtriangles)
10269                 {
10270                         *e++ = element[0];
10271                         *e++ = element[1];
10272                         *e++ = element[2];
10273                         mesh->numtriangles++;
10274                 }
10275                 element[1] = element[2];
10276         }
10277 }
10278
10279 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10280 {
10281         int i;
10282         int *e, element[3];
10283         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10284         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10285         e = mesh->element3i + mesh->numtriangles * 3;
10286         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10287         {
10288                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10289                 if (mesh->numtriangles < mesh->maxtriangles)
10290                 {
10291                         *e++ = element[0];
10292                         *e++ = element[1];
10293                         *e++ = element[2];
10294                         mesh->numtriangles++;
10295                 }
10296                 element[1] = element[2];
10297         }
10298 }
10299
10300 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10301 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10302 {
10303         int planenum, planenum2;
10304         int w;
10305         int tempnumpoints;
10306         mplane_t *plane, *plane2;
10307         double maxdist;
10308         double temppoints[2][256*3];
10309         // figure out how large a bounding box we need to properly compute this brush
10310         maxdist = 0;
10311         for (w = 0;w < numplanes;w++)
10312                 maxdist = max(maxdist, fabs(planes[w].dist));
10313         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10314         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10315         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10316         {
10317                 w = 0;
10318                 tempnumpoints = 4;
10319                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10320                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10321                 {
10322                         if (planenum2 == planenum)
10323                                 continue;
10324                         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);
10325                         w = !w;
10326                 }
10327                 if (tempnumpoints < 3)
10328                         continue;
10329                 // generate elements forming a triangle fan for this polygon
10330                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10331         }
10332 }
10333
10334 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)
10335 {
10336         texturelayer_t *layer;
10337         layer = t->currentlayers + t->currentnumlayers++;
10338         layer->type = type;
10339         layer->depthmask = depthmask;
10340         layer->blendfunc1 = blendfunc1;
10341         layer->blendfunc2 = blendfunc2;
10342         layer->texture = texture;
10343         layer->texmatrix = *matrix;
10344         layer->color[0] = r;
10345         layer->color[1] = g;
10346         layer->color[2] = b;
10347         layer->color[3] = a;
10348 }
10349
10350 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10351 {
10352         if(parms[0] == 0 && parms[1] == 0)
10353                 return false;
10354         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10355                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10356                         return false;
10357         return true;
10358 }
10359
10360 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10361 {
10362         double index, f;
10363         index = parms[2] + r_refdef.scene.time * parms[3];
10364         index -= floor(index);
10365         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10366         {
10367         default:
10368         case Q3WAVEFUNC_NONE:
10369         case Q3WAVEFUNC_NOISE:
10370         case Q3WAVEFUNC_COUNT:
10371                 f = 0;
10372                 break;
10373         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10374         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10375         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10376         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10377         case Q3WAVEFUNC_TRIANGLE:
10378                 index *= 4;
10379                 f = index - floor(index);
10380                 if (index < 1)
10381                         f = f;
10382                 else if (index < 2)
10383                         f = 1 - f;
10384                 else if (index < 3)
10385                         f = -f;
10386                 else
10387                         f = -(1 - f);
10388                 break;
10389         }
10390         f = parms[0] + parms[1] * f;
10391         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10392                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10393         return (float) f;
10394 }
10395
10396 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10397 {
10398         int w, h, idx;
10399         float f;
10400         float tcmat[12];
10401         matrix4x4_t matrix, temp;
10402         switch(tcmod->tcmod)
10403         {
10404                 case Q3TCMOD_COUNT:
10405                 case Q3TCMOD_NONE:
10406                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10407                                 matrix = r_waterscrollmatrix;
10408                         else
10409                                 matrix = identitymatrix;
10410                         break;
10411                 case Q3TCMOD_ENTITYTRANSLATE:
10412                         // this is used in Q3 to allow the gamecode to control texcoord
10413                         // scrolling on the entity, which is not supported in darkplaces yet.
10414                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10415                         break;
10416                 case Q3TCMOD_ROTATE:
10417                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10418                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10419                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10420                         break;
10421                 case Q3TCMOD_SCALE:
10422                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10423                         break;
10424                 case Q3TCMOD_SCROLL:
10425                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10426                         break;
10427                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10428                         w = (int) tcmod->parms[0];
10429                         h = (int) tcmod->parms[1];
10430                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10431                         f = f - floor(f);
10432                         idx = (int) floor(f * w * h);
10433                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10434                         break;
10435                 case Q3TCMOD_STRETCH:
10436                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10437                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10438                         break;
10439                 case Q3TCMOD_TRANSFORM:
10440                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10441                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10442                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10443                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10444                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10445                         break;
10446                 case Q3TCMOD_TURBULENT:
10447                         // this is handled in the RSurf_PrepareVertices function
10448                         matrix = identitymatrix;
10449                         break;
10450         }
10451         temp = *texmatrix;
10452         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10453 }
10454
10455 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10456 {
10457         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10458         char name[MAX_QPATH];
10459         skinframe_t *skinframe;
10460         unsigned char pixels[296*194];
10461         strlcpy(cache->name, skinname, sizeof(cache->name));
10462         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10463         if (developer_loading.integer)
10464                 Con_Printf("loading %s\n", name);
10465         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10466         if (!skinframe || !skinframe->base)
10467         {
10468                 unsigned char *f;
10469                 fs_offset_t filesize;
10470                 skinframe = NULL;
10471                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10472                 if (f)
10473                 {
10474                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10475                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10476                         Mem_Free(f);
10477                 }
10478         }
10479         cache->skinframe = skinframe;
10480 }
10481
10482 texture_t *R_GetCurrentTexture(texture_t *t)
10483 {
10484         int i;
10485         const entity_render_t *ent = rsurface.entity;
10486         dp_model_t *model = ent->model;
10487         q3shaderinfo_layer_tcmod_t *tcmod;
10488
10489         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10490                 return t->currentframe;
10491         t->update_lastrenderframe = r_textureframe;
10492         t->update_lastrenderentity = (void *)ent;
10493
10494         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10495                 t->camera_entity = ent->entitynumber;
10496         else
10497                 t->camera_entity = 0;
10498
10499         // switch to an alternate material if this is a q1bsp animated material
10500         {
10501                 texture_t *texture = t;
10502                 int s = rsurface.ent_skinnum;
10503                 if ((unsigned int)s >= (unsigned int)model->numskins)
10504                         s = 0;
10505                 if (model->skinscenes)
10506                 {
10507                         if (model->skinscenes[s].framecount > 1)
10508                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10509                         else
10510                                 s = model->skinscenes[s].firstframe;
10511                 }
10512                 if (s > 0)
10513                         t = t + s * model->num_surfaces;
10514                 if (t->animated)
10515                 {
10516                         // use an alternate animation if the entity's frame is not 0,
10517                         // and only if the texture has an alternate animation
10518                         if (rsurface.ent_alttextures && t->anim_total[1])
10519                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10520                         else
10521                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10522                 }
10523                 texture->currentframe = t;
10524         }
10525
10526         // update currentskinframe to be a qw skin or animation frame
10527         if (rsurface.ent_qwskin >= 0)
10528         {
10529                 i = rsurface.ent_qwskin;
10530                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10531                 {
10532                         r_qwskincache_size = cl.maxclients;
10533                         if (r_qwskincache)
10534                                 Mem_Free(r_qwskincache);
10535                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10536                 }
10537                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10538                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10539                 t->currentskinframe = r_qwskincache[i].skinframe;
10540                 if (t->currentskinframe == NULL)
10541                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10542         }
10543         else if (t->numskinframes >= 2)
10544                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10545         if (t->backgroundnumskinframes >= 2)
10546                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10547
10548         t->currentmaterialflags = t->basematerialflags;
10549         t->currentalpha = rsurface.colormod[3];
10550         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10551                 t->currentalpha *= r_wateralpha.value;
10552         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10553                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10554         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10555                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10556         if (!(rsurface.ent_flags & RENDER_LIGHT))
10557                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10558         else if (FAKELIGHT_ENABLED)
10559         {
10560                         // no modellight if using fakelight for the map
10561         }
10562         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10563         {
10564                 // pick a model lighting mode
10565                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10566                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10567                 else
10568                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10569         }
10570         if (rsurface.ent_flags & RENDER_ADDITIVE)
10571                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10572         else if (t->currentalpha < 1)
10573                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10574         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10575                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10576         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10577                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10578         if (t->backgroundnumskinframes)
10579                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10580         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10581         {
10582                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10583                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10584         }
10585         else
10586                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10587         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10588                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10589
10590         // there is no tcmod
10591         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10592         {
10593                 t->currenttexmatrix = r_waterscrollmatrix;
10594                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10595         }
10596         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10597         {
10598                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10599                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10600         }
10601
10602         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10603                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10604         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10605                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10606
10607         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10608         if (t->currentskinframe->qpixels)
10609                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10610         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10611         if (!t->basetexture)
10612                 t->basetexture = r_texture_notexture;
10613         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10614         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10615         t->nmaptexture = t->currentskinframe->nmap;
10616         if (!t->nmaptexture)
10617                 t->nmaptexture = r_texture_blanknormalmap;
10618         t->glosstexture = r_texture_black;
10619         t->glowtexture = t->currentskinframe->glow;
10620         t->fogtexture = t->currentskinframe->fog;
10621         t->reflectmasktexture = t->currentskinframe->reflect;
10622         if (t->backgroundnumskinframes)
10623         {
10624                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10625                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10626                 t->backgroundglosstexture = r_texture_black;
10627                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10628                 if (!t->backgroundnmaptexture)
10629                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10630         }
10631         else
10632         {
10633                 t->backgroundbasetexture = r_texture_white;
10634                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10635                 t->backgroundglosstexture = r_texture_black;
10636                 t->backgroundglowtexture = NULL;
10637         }
10638         t->specularpower = r_shadow_glossexponent.value;
10639         // TODO: store reference values for these in the texture?
10640         t->specularscale = 0;
10641         if (r_shadow_gloss.integer > 0)
10642         {
10643                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10644                 {
10645                         if (r_shadow_glossintensity.value > 0)
10646                         {
10647                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10648                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10649                                 t->specularscale = r_shadow_glossintensity.value;
10650                         }
10651                 }
10652                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10653                 {
10654                         t->glosstexture = r_texture_white;
10655                         t->backgroundglosstexture = r_texture_white;
10656                         t->specularscale = r_shadow_gloss2intensity.value;
10657                         t->specularpower = r_shadow_gloss2exponent.value;
10658                 }
10659         }
10660         t->specularscale *= t->specularscalemod;
10661         t->specularpower *= t->specularpowermod;
10662
10663         // lightmaps mode looks bad with dlights using actual texturing, so turn
10664         // off the colormap and glossmap, but leave the normalmap on as it still
10665         // accurately represents the shading involved
10666         if (gl_lightmaps.integer)
10667         {
10668                 t->basetexture = r_texture_grey128;
10669                 t->pantstexture = r_texture_black;
10670                 t->shirttexture = r_texture_black;
10671                 t->nmaptexture = r_texture_blanknormalmap;
10672                 t->glosstexture = r_texture_black;
10673                 t->glowtexture = NULL;
10674                 t->fogtexture = NULL;
10675                 t->reflectmasktexture = NULL;
10676                 t->backgroundbasetexture = NULL;
10677                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10678                 t->backgroundglosstexture = r_texture_black;
10679                 t->backgroundglowtexture = NULL;
10680                 t->specularscale = 0;
10681                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10682         }
10683
10684         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10685         VectorClear(t->dlightcolor);
10686         t->currentnumlayers = 0;
10687         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10688         {
10689                 int blendfunc1, blendfunc2;
10690                 qboolean depthmask;
10691                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10692                 {
10693                         blendfunc1 = GL_SRC_ALPHA;
10694                         blendfunc2 = GL_ONE;
10695                 }
10696                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10697                 {
10698                         blendfunc1 = GL_SRC_ALPHA;
10699                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10700                 }
10701                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10702                 {
10703                         blendfunc1 = t->customblendfunc[0];
10704                         blendfunc2 = t->customblendfunc[1];
10705                 }
10706                 else
10707                 {
10708                         blendfunc1 = GL_ONE;
10709                         blendfunc2 = GL_ZERO;
10710                 }
10711                 // don't colormod evilblend textures
10712                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10713                         VectorSet(t->lightmapcolor, 1, 1, 1);
10714                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10715                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10716                 {
10717                         // fullbright is not affected by r_refdef.lightmapintensity
10718                         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]);
10719                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10720                                 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]);
10721                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10722                                 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]);
10723                 }
10724                 else
10725                 {
10726                         vec3_t ambientcolor;
10727                         float colorscale;
10728                         // set the color tint used for lights affecting this surface
10729                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10730                         colorscale = 2;
10731                         // q3bsp has no lightmap updates, so the lightstylevalue that
10732                         // would normally be baked into the lightmap must be
10733                         // applied to the color
10734                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10735                         if (model->type == mod_brushq3)
10736                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10737                         colorscale *= r_refdef.lightmapintensity;
10738                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10739                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10740                         // basic lit geometry
10741                         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]);
10742                         // add pants/shirt if needed
10743                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10744                                 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]);
10745                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10746                                 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]);
10747                         // now add ambient passes if needed
10748                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10749                         {
10750                                 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]);
10751                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10752                                         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]);
10753                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10754                                         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]);
10755                         }
10756                 }
10757                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10758                         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]);
10759                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10760                 {
10761                         // if this is opaque use alpha blend which will darken the earlier
10762                         // passes cheaply.
10763                         //
10764                         // if this is an alpha blended material, all the earlier passes
10765                         // were darkened by fog already, so we only need to add the fog
10766                         // color ontop through the fog mask texture
10767                         //
10768                         // if this is an additive blended material, all the earlier passes
10769                         // were darkened by fog already, and we should not add fog color
10770                         // (because the background was not darkened, there is no fog color
10771                         // that was lost behind it).
10772                         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]);
10773                 }
10774         }
10775
10776         return t->currentframe;
10777 }
10778
10779 rsurfacestate_t rsurface;
10780
10781 void R_Mesh_ResizeArrays(int newvertices)
10782 {
10783         unsigned char *base;
10784         size_t size;
10785         if (rsurface.array_size >= newvertices)
10786                 return;
10787         if (rsurface.array_base)
10788                 Mem_Free(rsurface.array_base);
10789         rsurface.array_size = (newvertices + 1023) & ~1023;
10790         size = 0;
10791         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10792         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10793         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10794         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10795         size += rsurface.array_size * sizeof(float[3]);
10796         size += rsurface.array_size * sizeof(float[3]);
10797         size += rsurface.array_size * sizeof(float[3]);
10798         size += rsurface.array_size * sizeof(float[3]);
10799         size += rsurface.array_size * sizeof(float[3]);
10800         size += rsurface.array_size * sizeof(float[3]);
10801         size += rsurface.array_size * sizeof(float[3]);
10802         size += rsurface.array_size * sizeof(float[3]);
10803         size += rsurface.array_size * sizeof(float[4]);
10804         size += rsurface.array_size * sizeof(float[2]);
10805         size += rsurface.array_size * sizeof(float[2]);
10806         size += rsurface.array_size * sizeof(float[4]);
10807         size += rsurface.array_size * sizeof(int[3]);
10808         size += rsurface.array_size * sizeof(unsigned short[3]);
10809         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10810         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10811         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10812         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10813         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10814         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10815         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10816         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10817         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10818         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10819         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10820         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10821         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10822         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10823         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10824         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10825         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10826         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10827         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10828 }
10829
10830 void RSurf_ActiveWorldEntity(void)
10831 {
10832         dp_model_t *model = r_refdef.scene.worldmodel;
10833         //if (rsurface.entity == r_refdef.scene.worldentity)
10834         //      return;
10835         rsurface.entity = r_refdef.scene.worldentity;
10836         rsurface.skeleton = NULL;
10837         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10838         rsurface.ent_skinnum = 0;
10839         rsurface.ent_qwskin = -1;
10840         rsurface.ent_shadertime = 0;
10841         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10842         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10843         rsurface.matrix = identitymatrix;
10844         rsurface.inversematrix = identitymatrix;
10845         rsurface.matrixscale = 1;
10846         rsurface.inversematrixscale = 1;
10847         R_EntityMatrix(&identitymatrix);
10848         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10849         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10850         rsurface.fograngerecip = r_refdef.fograngerecip;
10851         rsurface.fogheightfade = r_refdef.fogheightfade;
10852         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10853         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10854         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10855         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10856         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10857         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10858         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10859         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10860         rsurface.colormod[3] = 1;
10861         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);
10862         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10863         rsurface.frameblend[0].lerp = 1;
10864         rsurface.ent_alttextures = false;
10865         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10866         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10867         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10868         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10869         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10870         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10871         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10872         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10873         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10874         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10875         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10876         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10877         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10878         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10879         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10880         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10881         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10882         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10883         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10884         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10885         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10886         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10887         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10888         rsurface.modelelement3i = model->surfmesh.data_element3i;
10889         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10890         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10891         rsurface.modelelement3s = model->surfmesh.data_element3s;
10892         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10893         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10894         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10895         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10896         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10897         rsurface.modelsurfaces = model->data_surfaces;
10898         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10899         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10900         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10901         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10902         rsurface.modelgeneratedvertex = false;
10903         rsurface.batchgeneratedvertex = false;
10904         rsurface.batchfirstvertex = 0;
10905         rsurface.batchnumvertices = 0;
10906         rsurface.batchfirsttriangle = 0;
10907         rsurface.batchnumtriangles = 0;
10908         rsurface.batchvertex3f  = NULL;
10909         rsurface.batchvertex3f_vertexbuffer = NULL;
10910         rsurface.batchvertex3f_bufferoffset = 0;
10911         rsurface.batchsvector3f = NULL;
10912         rsurface.batchsvector3f_vertexbuffer = NULL;
10913         rsurface.batchsvector3f_bufferoffset = 0;
10914         rsurface.batchtvector3f = NULL;
10915         rsurface.batchtvector3f_vertexbuffer = NULL;
10916         rsurface.batchtvector3f_bufferoffset = 0;
10917         rsurface.batchnormal3f  = NULL;
10918         rsurface.batchnormal3f_vertexbuffer = NULL;
10919         rsurface.batchnormal3f_bufferoffset = 0;
10920         rsurface.batchlightmapcolor4f = NULL;
10921         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10922         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10923         rsurface.batchtexcoordtexture2f = NULL;
10924         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10925         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10926         rsurface.batchtexcoordlightmap2f = NULL;
10927         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10928         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10929         rsurface.batchvertexmesh = NULL;
10930         rsurface.batchvertexmeshbuffer = NULL;
10931         rsurface.batchvertexposition = NULL;
10932         rsurface.batchvertexpositionbuffer = NULL;
10933         rsurface.batchelement3i = NULL;
10934         rsurface.batchelement3i_indexbuffer = NULL;
10935         rsurface.batchelement3i_bufferoffset = 0;
10936         rsurface.batchelement3s = NULL;
10937         rsurface.batchelement3s_indexbuffer = NULL;
10938         rsurface.batchelement3s_bufferoffset = 0;
10939         rsurface.passcolor4f = NULL;
10940         rsurface.passcolor4f_vertexbuffer = NULL;
10941         rsurface.passcolor4f_bufferoffset = 0;
10942 }
10943
10944 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10945 {
10946         dp_model_t *model = ent->model;
10947         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10948         //      return;
10949         rsurface.entity = (entity_render_t *)ent;
10950         rsurface.skeleton = ent->skeleton;
10951         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10952         rsurface.ent_skinnum = ent->skinnum;
10953         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;
10954         rsurface.ent_shadertime = ent->shadertime;
10955         rsurface.ent_flags = ent->flags;
10956         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10957         rsurface.matrix = ent->matrix;
10958         rsurface.inversematrix = ent->inversematrix;
10959         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10960         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10961         R_EntityMatrix(&rsurface.matrix);
10962         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10963         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10964         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10965         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10966         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10967         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10968         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10969         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10970         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10971         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10972         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10973         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10974         rsurface.colormod[3] = ent->alpha;
10975         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10976         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10977         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10978         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10979         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10980         if (ent->model->brush.submodel && !prepass)
10981         {
10982                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10983                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10984         }
10985         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10986         {
10987                 if (ent->animcache_vertex3f && !r_framedata_failed)
10988                 {
10989                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10990                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10991                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10992                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10993                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10994                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10995                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10996                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10997                 }
10998                 else if (wanttangents)
10999                 {
11000                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11001                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11002                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11003                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11004                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11005                         rsurface.modelvertexmesh = NULL;
11006                         rsurface.modelvertexmeshbuffer = NULL;
11007                         rsurface.modelvertexposition = NULL;
11008                         rsurface.modelvertexpositionbuffer = NULL;
11009                 }
11010                 else if (wantnormals)
11011                 {
11012                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11013                         rsurface.modelsvector3f = NULL;
11014                         rsurface.modeltvector3f = NULL;
11015                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11016                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11017                         rsurface.modelvertexmesh = NULL;
11018                         rsurface.modelvertexmeshbuffer = NULL;
11019                         rsurface.modelvertexposition = NULL;
11020                         rsurface.modelvertexpositionbuffer = NULL;
11021                 }
11022                 else
11023                 {
11024                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11025                         rsurface.modelsvector3f = NULL;
11026                         rsurface.modeltvector3f = NULL;
11027                         rsurface.modelnormal3f = NULL;
11028                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11029                         rsurface.modelvertexmesh = NULL;
11030                         rsurface.modelvertexmeshbuffer = NULL;
11031                         rsurface.modelvertexposition = NULL;
11032                         rsurface.modelvertexpositionbuffer = NULL;
11033                 }
11034                 rsurface.modelvertex3f_vertexbuffer = 0;
11035                 rsurface.modelvertex3f_bufferoffset = 0;
11036                 rsurface.modelsvector3f_vertexbuffer = 0;
11037                 rsurface.modelsvector3f_bufferoffset = 0;
11038                 rsurface.modeltvector3f_vertexbuffer = 0;
11039                 rsurface.modeltvector3f_bufferoffset = 0;
11040                 rsurface.modelnormal3f_vertexbuffer = 0;
11041                 rsurface.modelnormal3f_bufferoffset = 0;
11042                 rsurface.modelgeneratedvertex = true;
11043         }
11044         else
11045         {
11046                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11047                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11048                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11049                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11050                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11051                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11052                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11053                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11054                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11055                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11056                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11057                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11058                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11059                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11060                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11061                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11062                 rsurface.modelgeneratedvertex = false;
11063         }
11064         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11065         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11067         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11068         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11070         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11071         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11073         rsurface.modelelement3i = model->surfmesh.data_element3i;
11074         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11075         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11076         rsurface.modelelement3s = model->surfmesh.data_element3s;
11077         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11078         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11079         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11080         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11081         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11082         rsurface.modelsurfaces = model->data_surfaces;
11083         rsurface.batchgeneratedvertex = false;
11084         rsurface.batchfirstvertex = 0;
11085         rsurface.batchnumvertices = 0;
11086         rsurface.batchfirsttriangle = 0;
11087         rsurface.batchnumtriangles = 0;
11088         rsurface.batchvertex3f  = NULL;
11089         rsurface.batchvertex3f_vertexbuffer = NULL;
11090         rsurface.batchvertex3f_bufferoffset = 0;
11091         rsurface.batchsvector3f = NULL;
11092         rsurface.batchsvector3f_vertexbuffer = NULL;
11093         rsurface.batchsvector3f_bufferoffset = 0;
11094         rsurface.batchtvector3f = NULL;
11095         rsurface.batchtvector3f_vertexbuffer = NULL;
11096         rsurface.batchtvector3f_bufferoffset = 0;
11097         rsurface.batchnormal3f  = NULL;
11098         rsurface.batchnormal3f_vertexbuffer = NULL;
11099         rsurface.batchnormal3f_bufferoffset = 0;
11100         rsurface.batchlightmapcolor4f = NULL;
11101         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11102         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11103         rsurface.batchtexcoordtexture2f = NULL;
11104         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11105         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11106         rsurface.batchtexcoordlightmap2f = NULL;
11107         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11108         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11109         rsurface.batchvertexmesh = NULL;
11110         rsurface.batchvertexmeshbuffer = NULL;
11111         rsurface.batchvertexposition = NULL;
11112         rsurface.batchvertexpositionbuffer = NULL;
11113         rsurface.batchelement3i = NULL;
11114         rsurface.batchelement3i_indexbuffer = NULL;
11115         rsurface.batchelement3i_bufferoffset = 0;
11116         rsurface.batchelement3s = NULL;
11117         rsurface.batchelement3s_indexbuffer = NULL;
11118         rsurface.batchelement3s_bufferoffset = 0;
11119         rsurface.passcolor4f = NULL;
11120         rsurface.passcolor4f_vertexbuffer = NULL;
11121         rsurface.passcolor4f_bufferoffset = 0;
11122 }
11123
11124 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)
11125 {
11126         int i;
11127
11128         rsurface.entity = r_refdef.scene.worldentity;
11129         rsurface.skeleton = NULL;
11130         rsurface.ent_skinnum = 0;
11131         rsurface.ent_qwskin = -1;
11132         rsurface.ent_shadertime = shadertime;
11133         rsurface.ent_flags = entflags;
11134         rsurface.modelnumvertices = numvertices;
11135         rsurface.modelnumtriangles = numtriangles;
11136         R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11137         rsurface.matrix = *matrix;
11138         rsurface.inversematrix = *inversematrix;
11139         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11140         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11141         R_EntityMatrix(&rsurface.matrix);
11142         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11143         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11144         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11145         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11146         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11147         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11148         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11149         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11150         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11151         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11152         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11153         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11154         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);
11155         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11156         rsurface.frameblend[0].lerp = 1;
11157         rsurface.ent_alttextures = false;
11158         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11159         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11160         if (wanttangents)
11161         {
11162                 rsurface.modelvertex3f = vertex3f;
11163                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11164                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11165                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11166         }
11167         else if (wantnormals)
11168         {
11169                 rsurface.modelvertex3f = vertex3f;
11170                 rsurface.modelsvector3f = NULL;
11171                 rsurface.modeltvector3f = NULL;
11172                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11173         }
11174         else
11175         {
11176                 rsurface.modelvertex3f = vertex3f;
11177                 rsurface.modelsvector3f = NULL;
11178                 rsurface.modeltvector3f = NULL;
11179                 rsurface.modelnormal3f = NULL;
11180         }
11181         rsurface.modelvertexmesh = NULL;
11182         rsurface.modelvertexmeshbuffer = NULL;
11183         rsurface.modelvertexposition = NULL;
11184         rsurface.modelvertexpositionbuffer = NULL;
11185         rsurface.modelvertex3f_vertexbuffer = 0;
11186         rsurface.modelvertex3f_bufferoffset = 0;
11187         rsurface.modelsvector3f_vertexbuffer = 0;
11188         rsurface.modelsvector3f_bufferoffset = 0;
11189         rsurface.modeltvector3f_vertexbuffer = 0;
11190         rsurface.modeltvector3f_bufferoffset = 0;
11191         rsurface.modelnormal3f_vertexbuffer = 0;
11192         rsurface.modelnormal3f_bufferoffset = 0;
11193         rsurface.modelgeneratedvertex = true;
11194         rsurface.modellightmapcolor4f  = color4f;
11195         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11196         rsurface.modellightmapcolor4f_bufferoffset = 0;
11197         rsurface.modeltexcoordtexture2f  = texcoord2f;
11198         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11199         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11200         rsurface.modeltexcoordlightmap2f  = NULL;
11201         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11202         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11203         rsurface.modelelement3i = element3i;
11204         rsurface.modelelement3i_indexbuffer = NULL;
11205         rsurface.modelelement3i_bufferoffset = 0;
11206         rsurface.modelelement3s = element3s;
11207         rsurface.modelelement3s_indexbuffer = NULL;
11208         rsurface.modelelement3s_bufferoffset = 0;
11209         rsurface.modellightmapoffsets = NULL;
11210         rsurface.modelsurfaces = NULL;
11211         rsurface.batchgeneratedvertex = false;
11212         rsurface.batchfirstvertex = 0;
11213         rsurface.batchnumvertices = 0;
11214         rsurface.batchfirsttriangle = 0;
11215         rsurface.batchnumtriangles = 0;
11216         rsurface.batchvertex3f  = NULL;
11217         rsurface.batchvertex3f_vertexbuffer = NULL;
11218         rsurface.batchvertex3f_bufferoffset = 0;
11219         rsurface.batchsvector3f = NULL;
11220         rsurface.batchsvector3f_vertexbuffer = NULL;
11221         rsurface.batchsvector3f_bufferoffset = 0;
11222         rsurface.batchtvector3f = NULL;
11223         rsurface.batchtvector3f_vertexbuffer = NULL;
11224         rsurface.batchtvector3f_bufferoffset = 0;
11225         rsurface.batchnormal3f  = NULL;
11226         rsurface.batchnormal3f_vertexbuffer = NULL;
11227         rsurface.batchnormal3f_bufferoffset = 0;
11228         rsurface.batchlightmapcolor4f = NULL;
11229         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11230         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11231         rsurface.batchtexcoordtexture2f = NULL;
11232         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11233         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11234         rsurface.batchtexcoordlightmap2f = NULL;
11235         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11236         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11237         rsurface.batchvertexmesh = NULL;
11238         rsurface.batchvertexmeshbuffer = NULL;
11239         rsurface.batchvertexposition = NULL;
11240         rsurface.batchvertexpositionbuffer = NULL;
11241         rsurface.batchelement3i = NULL;
11242         rsurface.batchelement3i_indexbuffer = NULL;
11243         rsurface.batchelement3i_bufferoffset = 0;
11244         rsurface.batchelement3s = NULL;
11245         rsurface.batchelement3s_indexbuffer = NULL;
11246         rsurface.batchelement3s_bufferoffset = 0;
11247         rsurface.passcolor4f = NULL;
11248         rsurface.passcolor4f_vertexbuffer = NULL;
11249         rsurface.passcolor4f_bufferoffset = 0;
11250
11251         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11252         {
11253                 if ((wantnormals || wanttangents) && !normal3f)
11254                 {
11255                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11256                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11257                 }
11258                 if (wanttangents && !svector3f)
11259                 {
11260                         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);
11261                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11262                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11263                 }
11264         }
11265
11266         // now convert arrays into vertexmesh structs
11267         for (i = 0;i < numvertices;i++)
11268         {
11269                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11270                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11271                 if (rsurface.modelsvector3f)
11272                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11273                 if (rsurface.modeltvector3f)
11274                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11275                 if (rsurface.modelnormal3f)
11276                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11277                 if (rsurface.modellightmapcolor4f)
11278                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11279                 if (rsurface.modeltexcoordtexture2f)
11280                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11281                 if (rsurface.modeltexcoordlightmap2f)
11282                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11283         }
11284 }
11285
11286 float RSurf_FogPoint(const float *v)
11287 {
11288         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11289         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11290         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11291         float FogHeightFade = r_refdef.fogheightfade;
11292         float fogfrac;
11293         unsigned int fogmasktableindex;
11294         if (r_refdef.fogplaneviewabove)
11295                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11296         else
11297                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11298         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11299         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11300 }
11301
11302 float RSurf_FogVertex(const float *v)
11303 {
11304         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11305         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11306         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11307         float FogHeightFade = rsurface.fogheightfade;
11308         float fogfrac;
11309         unsigned int fogmasktableindex;
11310         if (r_refdef.fogplaneviewabove)
11311                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11312         else
11313                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11314         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11315         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11316 }
11317
11318 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11319 {
11320         int i;
11321         for (i = 0;i < numelements;i++)
11322                 outelement3i[i] = inelement3i[i] + adjust;
11323 }
11324
11325 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11326 extern cvar_t gl_vbo;
11327 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11328 {
11329         int deformindex;
11330         int firsttriangle;
11331         int numtriangles;
11332         int firstvertex;
11333         int endvertex;
11334         int numvertices;
11335         int surfacefirsttriangle;
11336         int surfacenumtriangles;
11337         int surfacefirstvertex;
11338         int surfaceendvertex;
11339         int surfacenumvertices;
11340         int needsupdate;
11341         int i, j;
11342         qboolean gaps;
11343         qboolean dynamicvertex;
11344         float amplitude;
11345         float animpos;
11346         float scale;
11347         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11348         float waveparms[4];
11349         q3shaderinfo_deform_t *deform;
11350         const msurface_t *surface, *firstsurface;
11351         r_vertexposition_t *vertexposition;
11352         r_vertexmesh_t *vertexmesh;
11353         if (!texturenumsurfaces)
11354                 return;
11355         // find vertex range of this surface batch
11356         gaps = false;
11357         firstsurface = texturesurfacelist[0];
11358         firsttriangle = firstsurface->num_firsttriangle;
11359         numtriangles = 0;
11360         firstvertex = endvertex = firstsurface->num_firstvertex;
11361         for (i = 0;i < texturenumsurfaces;i++)
11362         {
11363                 surface = texturesurfacelist[i];
11364                 if (surface != firstsurface + i)
11365                         gaps = true;
11366                 surfacefirstvertex = surface->num_firstvertex;
11367                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11368                 surfacenumtriangles = surface->num_triangles;
11369                 if (firstvertex > surfacefirstvertex)
11370                         firstvertex = surfacefirstvertex;
11371                 if (endvertex < surfaceendvertex)
11372                         endvertex = surfaceendvertex;
11373                 numtriangles += surfacenumtriangles;
11374         }
11375         if (!numtriangles)
11376                 return;
11377
11378         // we now know the vertex range used, and if there are any gaps in it
11379         rsurface.batchfirstvertex = firstvertex;
11380         rsurface.batchnumvertices = endvertex - firstvertex;
11381         rsurface.batchfirsttriangle = firsttriangle;
11382         rsurface.batchnumtriangles = numtriangles;
11383
11384         // this variable holds flags for which properties have been updated that
11385         // may require regenerating vertexmesh or vertexposition arrays...
11386         needsupdate = 0;
11387
11388         // check if any dynamic vertex processing must occur
11389         dynamicvertex = false;
11390
11391         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11392                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11393         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11394         {
11395                 switch (deform->deform)
11396                 {
11397                 default:
11398                 case Q3DEFORM_PROJECTIONSHADOW:
11399                 case Q3DEFORM_TEXT0:
11400                 case Q3DEFORM_TEXT1:
11401                 case Q3DEFORM_TEXT2:
11402                 case Q3DEFORM_TEXT3:
11403                 case Q3DEFORM_TEXT4:
11404                 case Q3DEFORM_TEXT5:
11405                 case Q3DEFORM_TEXT6:
11406                 case Q3DEFORM_TEXT7:
11407                 case Q3DEFORM_NONE:
11408                         break;
11409                 case Q3DEFORM_AUTOSPRITE:
11410                         dynamicvertex = true;
11411                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11412                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11413                         break;
11414                 case Q3DEFORM_AUTOSPRITE2:
11415                         dynamicvertex = true;
11416                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11417                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11418                         break;
11419                 case Q3DEFORM_NORMAL:
11420                         dynamicvertex = true;
11421                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11422                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11423                         break;
11424                 case Q3DEFORM_WAVE:
11425                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11426                                 break; // if wavefunc is a nop, ignore this transform
11427                         dynamicvertex = true;
11428                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11429                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11430                         break;
11431                 case Q3DEFORM_BULGE:
11432                         dynamicvertex = true;
11433                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11434                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11435                         break;
11436                 case Q3DEFORM_MOVE:
11437                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11438                                 break; // if wavefunc is a nop, ignore this transform
11439                         dynamicvertex = true;
11440                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11441                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11442                         break;
11443                 }
11444         }
11445         switch(rsurface.texture->tcgen.tcgen)
11446         {
11447         default:
11448         case Q3TCGEN_TEXTURE:
11449                 break;
11450         case Q3TCGEN_LIGHTMAP:
11451                 dynamicvertex = true;
11452                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11453                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11454                 break;
11455         case Q3TCGEN_VECTOR:
11456                 dynamicvertex = true;
11457                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11458                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11459                 break;
11460         case Q3TCGEN_ENVIRONMENT:
11461                 dynamicvertex = true;
11462                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11463                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11464                 break;
11465         }
11466         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11467         {
11468                 dynamicvertex = true;
11469                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11470                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11471         }
11472
11473         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11474         {
11475                 dynamicvertex = true;
11476                 batchneed |= BATCHNEED_NOGAPS;
11477                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11478         }
11479
11480         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11481         {
11482                 dynamicvertex = true;
11483                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11484                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11485         }
11486
11487         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11488         {
11489                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11490                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11491                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11492                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11493                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11494                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11495                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11496         }
11497
11498         // when the model data has no vertex buffer (dynamic mesh), we need to
11499         // eliminate gaps
11500         if (!rsurface.modelvertexmeshbuffer)
11501                 batchneed |= BATCHNEED_NOGAPS;
11502
11503         // if needsupdate, we have to do a dynamic vertex batch for sure
11504         if (needsupdate & batchneed)
11505                 dynamicvertex = true;
11506
11507         // see if we need to build vertexmesh from arrays
11508         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11509                 dynamicvertex = true;
11510
11511         // see if we need to build vertexposition from arrays
11512         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11513                 dynamicvertex = true;
11514
11515         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11516         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11517                 dynamicvertex = true;
11518
11519         // if there is a chance of animated vertex colors, it's a dynamic batch
11520         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11521                 dynamicvertex = true;
11522
11523         rsurface.batchvertex3f = rsurface.modelvertex3f;
11524         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11525         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11526         rsurface.batchsvector3f = rsurface.modelsvector3f;
11527         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11528         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11529         rsurface.batchtvector3f = rsurface.modeltvector3f;
11530         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11531         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11532         rsurface.batchnormal3f = rsurface.modelnormal3f;
11533         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11534         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11535         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11536         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11537         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11538         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11539         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11540         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11541         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11542         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11543         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11544         rsurface.batchvertexposition = rsurface.modelvertexposition;
11545         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11546         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11547         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11548         rsurface.batchelement3i = rsurface.modelelement3i;
11549         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11550         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11551         rsurface.batchelement3s = rsurface.modelelement3s;
11552         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11553         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11554
11555         // if any dynamic vertex processing has to occur in software, we copy the
11556         // entire surface list together before processing to rebase the vertices
11557         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11558         //
11559         // if any gaps exist and we do not have a static vertex buffer, we have to
11560         // copy the surface list together to avoid wasting upload bandwidth on the
11561         // vertices in the gaps.
11562         //
11563         // if gaps exist and we have a static vertex buffer, we still have to
11564         // combine the index buffer ranges into one dynamic index buffer.
11565         //
11566         // in all cases we end up with data that can be drawn in one call.
11567
11568         if (!dynamicvertex)
11569         {
11570                 // static vertex data, just set pointers...
11571                 rsurface.batchgeneratedvertex = false;
11572                 // if there are gaps, we want to build a combined index buffer,
11573                 // otherwise use the original static buffer with an appropriate offset
11574                 if (gaps)
11575                 {
11576                         firsttriangle = 0;
11577                         numtriangles = 0;
11578                         for (i = 0;i < texturenumsurfaces;i++)
11579                         {
11580                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11581                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11582                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11583                                 numtriangles += surfacenumtriangles;
11584                         }
11585                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11586                         rsurface.batchelement3i_indexbuffer = NULL;
11587                         rsurface.batchelement3i_bufferoffset = 0;
11588                         rsurface.batchelement3s = NULL;
11589                         rsurface.batchelement3s_indexbuffer = NULL;
11590                         rsurface.batchelement3s_bufferoffset = 0;
11591                         if (endvertex <= 65536)
11592                         {
11593                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11594                                 for (i = 0;i < numtriangles*3;i++)
11595                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11596                         }
11597                         rsurface.batchfirsttriangle = firsttriangle;
11598                         rsurface.batchnumtriangles = numtriangles;
11599                 }
11600                 return;
11601         }
11602
11603         // something needs software processing, do it for real...
11604         // we only directly handle interleaved array data in this case...
11605         rsurface.batchgeneratedvertex = true;
11606
11607         // now copy the vertex data into a combined array and make an index array
11608         // (this is what Quake3 does all the time)
11609         //if (gaps || rsurface.batchfirstvertex)
11610         {
11611                 rsurface.batchvertexposition = NULL;
11612                 rsurface.batchvertexpositionbuffer = NULL;
11613                 rsurface.batchvertexmesh = NULL;
11614                 rsurface.batchvertexmeshbuffer = NULL;
11615                 rsurface.batchvertex3f = NULL;
11616                 rsurface.batchvertex3f_vertexbuffer = NULL;
11617                 rsurface.batchvertex3f_bufferoffset = 0;
11618                 rsurface.batchsvector3f = NULL;
11619                 rsurface.batchsvector3f_vertexbuffer = NULL;
11620                 rsurface.batchsvector3f_bufferoffset = 0;
11621                 rsurface.batchtvector3f = NULL;
11622                 rsurface.batchtvector3f_vertexbuffer = NULL;
11623                 rsurface.batchtvector3f_bufferoffset = 0;
11624                 rsurface.batchnormal3f = NULL;
11625                 rsurface.batchnormal3f_vertexbuffer = NULL;
11626                 rsurface.batchnormal3f_bufferoffset = 0;
11627                 rsurface.batchlightmapcolor4f = NULL;
11628                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11629                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11630                 rsurface.batchtexcoordtexture2f = NULL;
11631                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11632                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11633                 rsurface.batchtexcoordlightmap2f = NULL;
11634                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11635                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11636                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11637                 rsurface.batchelement3i_indexbuffer = NULL;
11638                 rsurface.batchelement3i_bufferoffset = 0;
11639                 rsurface.batchelement3s = NULL;
11640                 rsurface.batchelement3s_indexbuffer = NULL;
11641                 rsurface.batchelement3s_bufferoffset = 0;
11642                 // we'll only be setting up certain arrays as needed
11643                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11644                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11645                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11646                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11647                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11648                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11649                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11650                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11651                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11652                 {
11653                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11654                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11655                 }
11656                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11657                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11658                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11659                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11660                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11661                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11662                 numvertices = 0;
11663                 numtriangles = 0;
11664                 for (i = 0;i < texturenumsurfaces;i++)
11665                 {
11666                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11667                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11668                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11669                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11670                         // copy only the data requested
11671                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11672                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11673                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11674                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11675                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11676                         {
11677                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11678                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11679                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11680                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11681                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11682                                 {
11683                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11684                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11685                                 }
11686                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11687                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11688                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11689                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11690                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11691                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11692                         }
11693                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11694                         numvertices += surfacenumvertices;
11695                         numtriangles += surfacenumtriangles;
11696                 }
11697
11698                 // generate a 16bit index array as well if possible
11699                 // (in general, dynamic batches fit)
11700                 if (numvertices <= 65536)
11701                 {
11702                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11703                         for (i = 0;i < numtriangles*3;i++)
11704                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11705                 }
11706
11707                 // since we've copied everything, the batch now starts at 0
11708                 rsurface.batchfirstvertex = 0;
11709                 rsurface.batchnumvertices = numvertices;
11710                 rsurface.batchfirsttriangle = 0;
11711                 rsurface.batchnumtriangles = numtriangles;
11712         }
11713
11714         // q1bsp surfaces rendered in vertex color mode have to have colors
11715         // calculated based on lightstyles
11716         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11717         {
11718                 // generate color arrays for the surfaces in this list
11719                 int c[4];
11720                 int scale;
11721                 int size3;
11722                 const int *offsets;
11723                 const unsigned char *lm;
11724                 numvertices = 0;
11725                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11726                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11727                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11728                 for (i = 0;i < texturenumsurfaces;i++)
11729                 {
11730                         surface = texturesurfacelist[i];
11731                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11732                         surfacenumvertices = surface->num_vertices;
11733                         if (surface->lightmapinfo->samples)
11734                         {
11735                                 for (j = 0;j < surfacenumvertices;j++)
11736                                 {
11737                                         lm = surface->lightmapinfo->samples + offsets[j];
11738                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11739                                         VectorScale(lm, scale, c);
11740                                         if (surface->lightmapinfo->styles[1] != 255)
11741                                         {
11742                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11743                                                 lm += size3;
11744                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11745                                                 VectorMA(c, scale, lm, c);
11746                                                 if (surface->lightmapinfo->styles[2] != 255)
11747                                                 {
11748                                                         lm += size3;
11749                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11750                                                         VectorMA(c, scale, lm, c);
11751                                                         if (surface->lightmapinfo->styles[3] != 255)
11752                                                         {
11753                                                                 lm += size3;
11754                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11755                                                                 VectorMA(c, scale, lm, c);
11756                                                         }
11757                                                 }
11758                                         }
11759                                         c[0] >>= 15;
11760                                         c[1] >>= 15;
11761                                         c[2] >>= 15;
11762                                         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);
11763                                         numvertices++;
11764                                 }
11765                         }
11766                         else
11767                         {
11768                                 for (j = 0;j < surfacenumvertices;j++)
11769                                 {
11770                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11771                                         numvertices++;
11772                                 }
11773                         }
11774                 }
11775         }
11776
11777         // if vertices are deformed (sprite flares and things in maps, possibly
11778         // water waves, bulges and other deformations), modify the copied vertices
11779         // in place
11780         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11781         {
11782                 switch (deform->deform)
11783                 {
11784                 default:
11785                 case Q3DEFORM_PROJECTIONSHADOW:
11786                 case Q3DEFORM_TEXT0:
11787                 case Q3DEFORM_TEXT1:
11788                 case Q3DEFORM_TEXT2:
11789                 case Q3DEFORM_TEXT3:
11790                 case Q3DEFORM_TEXT4:
11791                 case Q3DEFORM_TEXT5:
11792                 case Q3DEFORM_TEXT6:
11793                 case Q3DEFORM_TEXT7:
11794                 case Q3DEFORM_NONE:
11795                         break;
11796                 case Q3DEFORM_AUTOSPRITE:
11797                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11798                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11799                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11800                         VectorNormalize(newforward);
11801                         VectorNormalize(newright);
11802                         VectorNormalize(newup);
11803                         // a single autosprite surface can contain multiple sprites...
11804                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11805                         {
11806                                 VectorClear(center);
11807                                 for (i = 0;i < 4;i++)
11808                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11809                                 VectorScale(center, 0.25f, center);
11810                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11811                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11812                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11813                                 for (i = 0;i < 4;i++)
11814                                 {
11815                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11816                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11817                                 }
11818                         }
11819                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11820                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11821                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11822                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11823                         rsurface.batchvertex3f_vertexbuffer = NULL;
11824                         rsurface.batchvertex3f_bufferoffset = 0;
11825                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11826                         rsurface.batchsvector3f_vertexbuffer = NULL;
11827                         rsurface.batchsvector3f_bufferoffset = 0;
11828                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11829                         rsurface.batchtvector3f_vertexbuffer = NULL;
11830                         rsurface.batchtvector3f_bufferoffset = 0;
11831                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11832                         rsurface.batchnormal3f_vertexbuffer = NULL;
11833                         rsurface.batchnormal3f_bufferoffset = 0;
11834                         break;
11835                 case Q3DEFORM_AUTOSPRITE2:
11836                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11837                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11838                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11839                         VectorNormalize(newforward);
11840                         VectorNormalize(newright);
11841                         VectorNormalize(newup);
11842                         {
11843                                 const float *v1, *v2;
11844                                 vec3_t start, end;
11845                                 float f, l;
11846                                 struct
11847                                 {
11848                                         float length2;
11849                                         const float *v1;
11850                                         const float *v2;
11851                                 }
11852                                 shortest[2];
11853                                 memset(shortest, 0, sizeof(shortest));
11854                                 // a single autosprite surface can contain multiple sprites...
11855                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11856                                 {
11857                                         VectorClear(center);
11858                                         for (i = 0;i < 4;i++)
11859                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11860                                         VectorScale(center, 0.25f, center);
11861                                         // find the two shortest edges, then use them to define the
11862                                         // axis vectors for rotating around the central axis
11863                                         for (i = 0;i < 6;i++)
11864                                         {
11865                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11866                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11867                                                 l = VectorDistance2(v1, v2);
11868                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11869                                                 if (v1[2] != v2[2])
11870                                                         l += (1.0f / 1024.0f);
11871                                                 if (shortest[0].length2 > l || i == 0)
11872                                                 {
11873                                                         shortest[1] = shortest[0];
11874                                                         shortest[0].length2 = l;
11875                                                         shortest[0].v1 = v1;
11876                                                         shortest[0].v2 = v2;
11877                                                 }
11878                                                 else if (shortest[1].length2 > l || i == 1)
11879                                                 {
11880                                                         shortest[1].length2 = l;
11881                                                         shortest[1].v1 = v1;
11882                                                         shortest[1].v2 = v2;
11883                                                 }
11884                                         }
11885                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11886                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11887                                         // this calculates the right vector from the shortest edge
11888                                         // and the up vector from the edge midpoints
11889                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11890                                         VectorNormalize(right);
11891                                         VectorSubtract(end, start, up);
11892                                         VectorNormalize(up);
11893                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11894                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11895                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11896                                         VectorNegate(forward, forward);
11897                                         VectorReflect(forward, 0, up, forward);
11898                                         VectorNormalize(forward);
11899                                         CrossProduct(up, forward, newright);
11900                                         VectorNormalize(newright);
11901                                         // rotate the quad around the up axis vector, this is made
11902                                         // especially easy by the fact we know the quad is flat,
11903                                         // so we only have to subtract the center position and
11904                                         // measure distance along the right vector, and then
11905                                         // multiply that by the newright vector and add back the
11906                                         // center position
11907                                         // we also need to subtract the old position to undo the
11908                                         // displacement from the center, which we do with a
11909                                         // DotProduct, the subtraction/addition of center is also
11910                                         // optimized into DotProducts here
11911                                         l = DotProduct(right, center);
11912                                         for (i = 0;i < 4;i++)
11913                                         {
11914                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11915                                                 f = DotProduct(right, v1) - l;
11916                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11917                                         }
11918                                 }
11919                         }
11920                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11921                         rsurface.batchvertex3f_vertexbuffer = NULL;
11922                         rsurface.batchvertex3f_bufferoffset = 0;
11923                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11924                         {
11925                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11926                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11927                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11928                                 rsurface.batchnormal3f_bufferoffset = 0;
11929                         }
11930                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11931                         {
11932                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11933                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11934                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11935                                 rsurface.batchsvector3f_bufferoffset = 0;
11936                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11937                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11938                                 rsurface.batchtvector3f_bufferoffset = 0;
11939                         }
11940                         break;
11941                 case Q3DEFORM_NORMAL:
11942                         // deform the normals to make reflections wavey
11943                         for (j = 0;j < rsurface.batchnumvertices;j++)
11944                         {
11945                                 float vertex[3];
11946                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11947                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11948                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11949                                 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]);
11950                                 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]);
11951                                 VectorNormalize(normal);
11952                         }
11953                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11954                         rsurface.batchnormal3f_vertexbuffer = NULL;
11955                         rsurface.batchnormal3f_bufferoffset = 0;
11956                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11957                         {
11958                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11959                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11960                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11961                                 rsurface.batchsvector3f_bufferoffset = 0;
11962                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11963                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11964                                 rsurface.batchtvector3f_bufferoffset = 0;
11965                         }
11966                         break;
11967                 case Q3DEFORM_WAVE:
11968                         // deform vertex array to make wavey water and flags and such
11969                         waveparms[0] = deform->waveparms[0];
11970                         waveparms[1] = deform->waveparms[1];
11971                         waveparms[2] = deform->waveparms[2];
11972                         waveparms[3] = deform->waveparms[3];
11973                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11974                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11975                         // this is how a divisor of vertex influence on deformation
11976                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11977                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11978                         for (j = 0;j < rsurface.batchnumvertices;j++)
11979                         {
11980                                 // if the wavefunc depends on time, evaluate it per-vertex
11981                                 if (waveparms[3])
11982                                 {
11983                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11984                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11985                                 }
11986                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11987                         }
11988                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11989                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11990                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11991                         rsurface.batchvertex3f_vertexbuffer = NULL;
11992                         rsurface.batchvertex3f_bufferoffset = 0;
11993                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11994                         rsurface.batchnormal3f_vertexbuffer = NULL;
11995                         rsurface.batchnormal3f_bufferoffset = 0;
11996                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11997                         {
11998                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11999                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12000                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12001                                 rsurface.batchsvector3f_bufferoffset = 0;
12002                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12003                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12004                                 rsurface.batchtvector3f_bufferoffset = 0;
12005                         }
12006                         break;
12007                 case Q3DEFORM_BULGE:
12008                         // deform vertex array to make the surface have moving bulges
12009                         for (j = 0;j < rsurface.batchnumvertices;j++)
12010                         {
12011                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12012                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12013                         }
12014                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12015                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12016                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12017                         rsurface.batchvertex3f_vertexbuffer = NULL;
12018                         rsurface.batchvertex3f_bufferoffset = 0;
12019                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12020                         rsurface.batchnormal3f_vertexbuffer = NULL;
12021                         rsurface.batchnormal3f_bufferoffset = 0;
12022                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12023                         {
12024                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12025                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12026                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12027                                 rsurface.batchsvector3f_bufferoffset = 0;
12028                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12029                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12030                                 rsurface.batchtvector3f_bufferoffset = 0;
12031                         }
12032                         break;
12033                 case Q3DEFORM_MOVE:
12034                         // deform vertex array
12035                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12036                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12037                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12038                         VectorScale(deform->parms, scale, waveparms);
12039                         for (j = 0;j < rsurface.batchnumvertices;j++)
12040                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12041                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12042                         rsurface.batchvertex3f_vertexbuffer = NULL;
12043                         rsurface.batchvertex3f_bufferoffset = 0;
12044                         break;
12045                 }
12046         }
12047
12048         // generate texcoords based on the chosen texcoord source
12049         switch(rsurface.texture->tcgen.tcgen)
12050         {
12051         default:
12052         case Q3TCGEN_TEXTURE:
12053                 break;
12054         case Q3TCGEN_LIGHTMAP:
12055                 if (rsurface.batchtexcoordlightmap2f)
12056                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12057                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12058                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12059                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12060                 break;
12061         case Q3TCGEN_VECTOR:
12062                 for (j = 0;j < rsurface.batchnumvertices;j++)
12063                 {
12064                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12065                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12066                 }
12067                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12068                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12069                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12070                 break;
12071         case Q3TCGEN_ENVIRONMENT:
12072                 // make environment reflections using a spheremap
12073                 for (j = 0;j < rsurface.batchnumvertices;j++)
12074                 {
12075                         // identical to Q3A's method, but executed in worldspace so
12076                         // carried models can be shiny too
12077
12078                         float viewer[3], d, reflected[3], worldreflected[3];
12079
12080                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12081                         // VectorNormalize(viewer);
12082
12083                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12084
12085                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12086                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12087                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12088                         // note: this is proportinal to viewer, so we can normalize later
12089
12090                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12091                         VectorNormalize(worldreflected);
12092
12093                         // note: this sphere map only uses world x and z!
12094                         // so positive and negative y will LOOK THE SAME.
12095                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12096                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12097                 }
12098                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12099                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12100                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12101                 break;
12102         }
12103         // the only tcmod that needs software vertex processing is turbulent, so
12104         // check for it here and apply the changes if needed
12105         // and we only support that as the first one
12106         // (handling a mixture of turbulent and other tcmods would be problematic
12107         //  without punting it entirely to a software path)
12108         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12109         {
12110                 amplitude = rsurface.texture->tcmods[0].parms[1];
12111                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12112                 for (j = 0;j < rsurface.batchnumvertices;j++)
12113                 {
12114                         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);
12115                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12116                 }
12117                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12118                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12119                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12120         }
12121
12122         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12123         {
12124                 // convert the modified arrays to vertex structs
12125                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12126                 rsurface.batchvertexmeshbuffer = NULL;
12127                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12128                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12129                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12130                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12131                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12132                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12133                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12134                 {
12135                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12136                         {
12137                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12138                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12139                         }
12140                 }
12141                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12142                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12143                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12144                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12145                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12146                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12147                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12148                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12149                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12150         }
12151
12152         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12153         {
12154                 // convert the modified arrays to vertex structs
12155                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12156                 rsurface.batchvertexpositionbuffer = NULL;
12157                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12158                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12159                 else
12160                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12161                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12162         }
12163 }
12164
12165 void RSurf_DrawBatch(void)
12166 {
12167         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);
12168 }
12169
12170 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12171 {
12172         // pick the closest matching water plane
12173         int planeindex, vertexindex, bestplaneindex = -1;
12174         float d, bestd;
12175         vec3_t vert;
12176         const float *v;
12177         r_waterstate_waterplane_t *p;
12178         bestd = 0;
12179         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12180         {
12181                 if(p->camera_entity != rsurface.texture->camera_entity)
12182                         continue;
12183                 d = 0;
12184                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12185                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12186                 {
12187                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12188                         d += fabs(PlaneDiff(vert, &p->plane));
12189                 }
12190                 if (bestd > d || bestplaneindex < 0)
12191                 {
12192                         bestd = d;
12193                         bestplaneindex = planeindex;
12194                 }
12195         }
12196         return bestplaneindex;
12197 }
12198
12199 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12200 {
12201         int i;
12202         for (i = 0;i < rsurface.batchnumvertices;i++)
12203                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12204         rsurface.passcolor4f = rsurface.array_passcolor4f;
12205         rsurface.passcolor4f_vertexbuffer = 0;
12206         rsurface.passcolor4f_bufferoffset = 0;
12207 }
12208
12209 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12210 {
12211         int i;
12212         float f;
12213         const float *v;
12214         const float *c;
12215         float *c2;
12216         if (rsurface.passcolor4f)
12217         {
12218                 // generate color arrays
12219                 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)
12220                 {
12221                         f = RSurf_FogVertex(v);
12222                         c2[0] = c[0] * f;
12223                         c2[1] = c[1] * f;
12224                         c2[2] = c[2] * f;
12225                         c2[3] = c[3];
12226                 }
12227         }
12228         else
12229         {
12230                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12231                 {
12232                         f = RSurf_FogVertex(v);
12233                         c2[0] = f;
12234                         c2[1] = f;
12235                         c2[2] = f;
12236                         c2[3] = 1;
12237                 }
12238         }
12239         rsurface.passcolor4f = rsurface.array_passcolor4f;
12240         rsurface.passcolor4f_vertexbuffer = 0;
12241         rsurface.passcolor4f_bufferoffset = 0;
12242 }
12243
12244 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12245 {
12246         int i;
12247         float f;
12248         const float *v;
12249         const float *c;
12250         float *c2;
12251         if (!rsurface.passcolor4f)
12252                 return;
12253         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)
12254         {
12255                 f = RSurf_FogVertex(v);
12256                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12257                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12258                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12259                 c2[3] = c[3];
12260         }
12261         rsurface.passcolor4f = rsurface.array_passcolor4f;
12262         rsurface.passcolor4f_vertexbuffer = 0;
12263         rsurface.passcolor4f_bufferoffset = 0;
12264 }
12265
12266 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12267 {
12268         int i;
12269         const float *c;
12270         float *c2;
12271         if (!rsurface.passcolor4f)
12272                 return;
12273         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12274         {
12275                 c2[0] = c[0] * r;
12276                 c2[1] = c[1] * g;
12277                 c2[2] = c[2] * b;
12278                 c2[3] = c[3] * a;
12279         }
12280         rsurface.passcolor4f = rsurface.array_passcolor4f;
12281         rsurface.passcolor4f_vertexbuffer = 0;
12282         rsurface.passcolor4f_bufferoffset = 0;
12283 }
12284
12285 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12286 {
12287         int i;
12288         const float *c;
12289         float *c2;
12290         if (!rsurface.passcolor4f)
12291                 return;
12292         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12293         {
12294                 c2[0] = c[0] + r_refdef.scene.ambient;
12295                 c2[1] = c[1] + r_refdef.scene.ambient;
12296                 c2[2] = c[2] + r_refdef.scene.ambient;
12297                 c2[3] = c[3];
12298         }
12299         rsurface.passcolor4f = rsurface.array_passcolor4f;
12300         rsurface.passcolor4f_vertexbuffer = 0;
12301         rsurface.passcolor4f_bufferoffset = 0;
12302 }
12303
12304 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12305 {
12306         // TODO: optimize
12307         rsurface.passcolor4f = NULL;
12308         rsurface.passcolor4f_vertexbuffer = 0;
12309         rsurface.passcolor4f_bufferoffset = 0;
12310         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12311         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12312         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12313         GL_Color(r, g, b, a);
12314         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12315         RSurf_DrawBatch();
12316 }
12317
12318 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12319 {
12320         // TODO: optimize applyfog && applycolor case
12321         // just apply fog if necessary, and tint the fog color array if necessary
12322         rsurface.passcolor4f = NULL;
12323         rsurface.passcolor4f_vertexbuffer = 0;
12324         rsurface.passcolor4f_bufferoffset = 0;
12325         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12326         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12327         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12328         GL_Color(r, g, b, a);
12329         RSurf_DrawBatch();
12330 }
12331
12332 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12333 {
12334         // TODO: optimize
12335         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12336         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12337         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12338         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12339         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12340         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12341         GL_Color(r, g, b, a);
12342         RSurf_DrawBatch();
12343 }
12344
12345 static void RSurf_DrawBatch_GL11_ClampColor(void)
12346 {
12347         int i;
12348         const float *c1;
12349         float *c2;
12350         if (!rsurface.passcolor4f)
12351                 return;
12352         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12353         {
12354                 c2[0] = bound(0.0f, c1[0], 1.0f);
12355                 c2[1] = bound(0.0f, c1[1], 1.0f);
12356                 c2[2] = bound(0.0f, c1[2], 1.0f);
12357                 c2[3] = bound(0.0f, c1[3], 1.0f);
12358         }
12359 }
12360
12361 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12362 {
12363         int i;
12364         float f;
12365         const float *v;
12366         const float *n;
12367         float *c;
12368         //vec3_t eyedir;
12369
12370         // fake shading
12371         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)
12372         {
12373                 f = -DotProduct(r_refdef.view.forward, n);
12374                 f = max(0, f);
12375                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12376                 f *= r_refdef.lightmapintensity;
12377                 Vector4Set(c, f, f, f, 1);
12378         }
12379
12380         rsurface.passcolor4f = rsurface.array_passcolor4f;
12381         rsurface.passcolor4f_vertexbuffer = 0;
12382         rsurface.passcolor4f_bufferoffset = 0;
12383 }
12384
12385 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12386 {
12387         RSurf_DrawBatch_GL11_ApplyFakeLight();
12388         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12389         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12390         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12391         GL_Color(r, g, b, a);
12392         RSurf_DrawBatch();
12393 }
12394
12395 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12396 {
12397         int i;
12398         float f;
12399         float alpha;
12400         const float *v;
12401         const float *n;
12402         float *c;
12403         vec3_t ambientcolor;
12404         vec3_t diffusecolor;
12405         vec3_t lightdir;
12406         // TODO: optimize
12407         // model lighting
12408         VectorCopy(rsurface.modellight_lightdir, lightdir);
12409         f = 0.5f * r_refdef.lightmapintensity;
12410         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12411         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12412         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12413         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12414         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12415         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12416         alpha = *a;
12417         if (VectorLength2(diffusecolor) > 0)
12418         {
12419                 // q3-style directional shading
12420                 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)
12421                 {
12422                         if ((f = DotProduct(n, lightdir)) > 0)
12423                                 VectorMA(ambientcolor, f, diffusecolor, c);
12424                         else
12425                                 VectorCopy(ambientcolor, c);
12426                         c[3] = alpha;
12427                 }
12428                 *r = 1;
12429                 *g = 1;
12430                 *b = 1;
12431                 *a = 1;
12432                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12433                 rsurface.passcolor4f_vertexbuffer = 0;
12434                 rsurface.passcolor4f_bufferoffset = 0;
12435                 *applycolor = false;
12436         }
12437         else
12438         {
12439                 *r = ambientcolor[0];
12440                 *g = ambientcolor[1];
12441                 *b = ambientcolor[2];
12442                 rsurface.passcolor4f = NULL;
12443                 rsurface.passcolor4f_vertexbuffer = 0;
12444                 rsurface.passcolor4f_bufferoffset = 0;
12445         }
12446 }
12447
12448 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12449 {
12450         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12451         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12452         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12453         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12454         GL_Color(r, g, b, a);
12455         RSurf_DrawBatch();
12456 }
12457
12458 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12459 {
12460         int i;
12461         float f;
12462         const float *v;
12463         float *c;
12464         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12465         {
12466                 f = 1 - RSurf_FogVertex(v);
12467                 c[0] = r;
12468                 c[1] = g;
12469                 c[2] = b;
12470                 c[3] = f * a;
12471         }
12472 }
12473
12474 void RSurf_SetupDepthAndCulling(void)
12475 {
12476         // submodels are biased to avoid z-fighting with world surfaces that they
12477         // may be exactly overlapping (avoids z-fighting artifacts on certain
12478         // doors and things in Quake maps)
12479         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12480         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12481         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12482         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12483 }
12484
12485 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12486 {
12487         // transparent sky would be ridiculous
12488         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12489                 return;
12490         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12491         skyrenderlater = true;
12492         RSurf_SetupDepthAndCulling();
12493         GL_DepthMask(true);
12494         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12495         // skymasking on them, and Quake3 never did sky masking (unlike
12496         // software Quake and software Quake2), so disable the sky masking
12497         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12498         // and skymasking also looks very bad when noclipping outside the
12499         // level, so don't use it then either.
12500         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12501         {
12502                 R_Mesh_ResetTextureState();
12503                 if (skyrendermasked)
12504                 {
12505                         R_SetupShader_DepthOrShadow();
12506                         // depth-only (masking)
12507                         GL_ColorMask(0,0,0,0);
12508                         // just to make sure that braindead drivers don't draw
12509                         // anything despite that colormask...
12510                         GL_BlendFunc(GL_ZERO, GL_ONE);
12511                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12512                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12513                 }
12514                 else
12515                 {
12516                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12517                         // fog sky
12518                         GL_BlendFunc(GL_ONE, GL_ZERO);
12519                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12520                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12521                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12522                 }
12523                 RSurf_DrawBatch();
12524                 if (skyrendermasked)
12525                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12526         }
12527         R_Mesh_ResetTextureState();
12528         GL_Color(1, 1, 1, 1);
12529 }
12530
12531 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12532 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12533 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12534 {
12535         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12536                 return;
12537         if (prepass)
12538         {
12539                 // render screenspace normalmap to texture
12540                 GL_DepthMask(true);
12541                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12542                 RSurf_DrawBatch();
12543                 return;
12544         }
12545
12546         // bind lightmap texture
12547
12548         // water/refraction/reflection/camera surfaces have to be handled specially
12549         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12550         {
12551                 int start, end, startplaneindex;
12552                 for (start = 0;start < texturenumsurfaces;start = end)
12553                 {
12554                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12555                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12556                                 ;
12557                         // now that we have a batch using the same planeindex, render it
12558                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12559                         {
12560                                 // render water or distortion background
12561                                 GL_DepthMask(true);
12562                                 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));
12563                                 RSurf_DrawBatch();
12564                                 // blend surface on top
12565                                 GL_DepthMask(false);
12566                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12567                                 RSurf_DrawBatch();
12568                         }
12569                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12570                         {
12571                                 // render surface with reflection texture as input
12572                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12573                                 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));
12574                                 RSurf_DrawBatch();
12575                         }
12576                 }
12577                 return;
12578         }
12579
12580         // render surface batch normally
12581         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12582         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12583         RSurf_DrawBatch();
12584 }
12585
12586 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12587 {
12588         // OpenGL 1.3 path - anything not completely ancient
12589         qboolean applycolor;
12590         qboolean applyfog;
12591         int layerindex;
12592         const texturelayer_t *layer;
12593         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);
12594         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12595
12596         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12597         {
12598                 vec4_t layercolor;
12599                 int layertexrgbscale;
12600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12601                 {
12602                         if (layerindex == 0)
12603                                 GL_AlphaTest(true);
12604                         else
12605                         {
12606                                 GL_AlphaTest(false);
12607                                 GL_DepthFunc(GL_EQUAL);
12608                         }
12609                 }
12610                 GL_DepthMask(layer->depthmask && writedepth);
12611                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12612                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12613                 {
12614                         layertexrgbscale = 4;
12615                         VectorScale(layer->color, 0.25f, layercolor);
12616                 }
12617                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12618                 {
12619                         layertexrgbscale = 2;
12620                         VectorScale(layer->color, 0.5f, layercolor);
12621                 }
12622                 else
12623                 {
12624                         layertexrgbscale = 1;
12625                         VectorScale(layer->color, 1.0f, layercolor);
12626                 }
12627                 layercolor[3] = layer->color[3];
12628                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12629                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12630                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12631                 switch (layer->type)
12632                 {
12633                 case TEXTURELAYERTYPE_LITTEXTURE:
12634                         // single-pass lightmapped texture with 2x rgbscale
12635                         R_Mesh_TexBind(0, r_texture_white);
12636                         R_Mesh_TexMatrix(0, NULL);
12637                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12638                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12639                         R_Mesh_TexBind(1, layer->texture);
12640                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12641                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12642                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12643                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12644                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12645                         else if (FAKELIGHT_ENABLED)
12646                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12647                         else if (rsurface.uselightmaptexture)
12648                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12649                         else
12650                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12651                         break;
12652                 case TEXTURELAYERTYPE_TEXTURE:
12653                         // singletexture unlit texture with transparency support
12654                         R_Mesh_TexBind(0, layer->texture);
12655                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12656                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12657                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12658                         R_Mesh_TexBind(1, 0);
12659                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12660                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12661                         break;
12662                 case TEXTURELAYERTYPE_FOG:
12663                         // singletexture fogging
12664                         if (layer->texture)
12665                         {
12666                                 R_Mesh_TexBind(0, layer->texture);
12667                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12668                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12669                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12670                         }
12671                         else
12672                         {
12673                                 R_Mesh_TexBind(0, 0);
12674                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12675                         }
12676                         R_Mesh_TexBind(1, 0);
12677                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12678                         // generate a color array for the fog pass
12679                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12680                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12681                         RSurf_DrawBatch();
12682                         break;
12683                 default:
12684                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12685                 }
12686         }
12687         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12688         {
12689                 GL_DepthFunc(GL_LEQUAL);
12690                 GL_AlphaTest(false);
12691         }
12692 }
12693
12694 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12695 {
12696         // OpenGL 1.1 - crusty old voodoo path
12697         qboolean applyfog;
12698         int layerindex;
12699         const texturelayer_t *layer;
12700         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);
12701         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12702
12703         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12704         {
12705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12706                 {
12707                         if (layerindex == 0)
12708                                 GL_AlphaTest(true);
12709                         else
12710                         {
12711                                 GL_AlphaTest(false);
12712                                 GL_DepthFunc(GL_EQUAL);
12713                         }
12714                 }
12715                 GL_DepthMask(layer->depthmask && writedepth);
12716                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12717                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12718                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12719                 switch (layer->type)
12720                 {
12721                 case TEXTURELAYERTYPE_LITTEXTURE:
12722                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12723                         {
12724                                 // two-pass lit texture with 2x rgbscale
12725                                 // first the lightmap pass
12726                                 R_Mesh_TexBind(0, r_texture_white);
12727                                 R_Mesh_TexMatrix(0, NULL);
12728                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12729                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12730                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12731                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12732                                 else if (FAKELIGHT_ENABLED)
12733                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12734                                 else if (rsurface.uselightmaptexture)
12735                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12736                                 else
12737                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12738                                 // then apply the texture to it
12739                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12740                                 R_Mesh_TexBind(0, layer->texture);
12741                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12742                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12743                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12744                                 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);
12745                         }
12746                         else
12747                         {
12748                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12749                                 R_Mesh_TexBind(0, layer->texture);
12750                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12751                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12752                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12753                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12754                                         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);
12755                                 else
12756                                         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);
12757                         }
12758                         break;
12759                 case TEXTURELAYERTYPE_TEXTURE:
12760                         // singletexture unlit texture with transparency support
12761                         R_Mesh_TexBind(0, layer->texture);
12762                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12763                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12764                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12765                         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);
12766                         break;
12767                 case TEXTURELAYERTYPE_FOG:
12768                         // singletexture fogging
12769                         if (layer->texture)
12770                         {
12771                                 R_Mesh_TexBind(0, layer->texture);
12772                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12773                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12774                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12775                         }
12776                         else
12777                         {
12778                                 R_Mesh_TexBind(0, 0);
12779                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12780                         }
12781                         // generate a color array for the fog pass
12782                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12783                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12784                         RSurf_DrawBatch();
12785                         break;
12786                 default:
12787                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12788                 }
12789         }
12790         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12791         {
12792                 GL_DepthFunc(GL_LEQUAL);
12793                 GL_AlphaTest(false);
12794         }
12795 }
12796
12797 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12798 {
12799         int vi;
12800         int j;
12801         r_vertexgeneric_t *batchvertex;
12802         float c[4];
12803
12804         GL_AlphaTest(false);
12805         R_Mesh_ResetTextureState();
12806         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12807
12808         if(rsurface.texture && rsurface.texture->currentskinframe)
12809         {
12810                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12811                 c[3] *= rsurface.texture->currentalpha;
12812         }
12813         else
12814         {
12815                 c[0] = 1;
12816                 c[1] = 0;
12817                 c[2] = 1;
12818                 c[3] = 1;
12819         }
12820
12821         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12822         {
12823                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12824                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12825                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12826         }
12827
12828         // brighten it up (as texture value 127 means "unlit")
12829         c[0] *= 2 * r_refdef.view.colorscale;
12830         c[1] *= 2 * r_refdef.view.colorscale;
12831         c[2] *= 2 * r_refdef.view.colorscale;
12832
12833         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12834                 c[3] *= r_wateralpha.value;
12835
12836         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12837         {
12838                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12839                 GL_DepthMask(false);
12840         }
12841         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12842         {
12843                 GL_BlendFunc(GL_ONE, GL_ONE);
12844                 GL_DepthMask(false);
12845         }
12846         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12847         {
12848                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12849                 GL_DepthMask(false);
12850         }
12851         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12852         {
12853                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12854                 GL_DepthMask(false);
12855         }
12856         else
12857         {
12858                 GL_BlendFunc(GL_ONE, GL_ZERO);
12859                 GL_DepthMask(writedepth);
12860         }
12861
12862         if (r_showsurfaces.integer == 3)
12863         {
12864                 rsurface.passcolor4f = NULL;
12865
12866                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12867                 {
12868                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12869
12870                         rsurface.passcolor4f = NULL;
12871                         rsurface.passcolor4f_vertexbuffer = 0;
12872                         rsurface.passcolor4f_bufferoffset = 0;
12873                 }
12874                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12875                 {
12876                         qboolean applycolor = true;
12877                         float one = 1.0;
12878
12879                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12880
12881                         r_refdef.lightmapintensity = 1;
12882                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12883                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12884                 }
12885                 else if (FAKELIGHT_ENABLED)
12886                 {
12887                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12888
12889                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12890                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12891                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12892                 }
12893                 else
12894                 {
12895                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12896
12897                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12898                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12899                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12900                 }
12901
12902                 if(!rsurface.passcolor4f)
12903                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12904
12905                 RSurf_DrawBatch_GL11_ApplyAmbient();
12906                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12907                 if(r_refdef.fogenabled)
12908                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12909                 RSurf_DrawBatch_GL11_ClampColor();
12910
12911                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12912                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12913                 RSurf_DrawBatch();
12914         }
12915         else if (!r_refdef.view.showdebug)
12916         {
12917                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12918                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12919                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12920                 {
12921                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12922                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12923                 }
12924                 R_Mesh_PrepareVertices_Generic_Unlock();
12925                 RSurf_DrawBatch();
12926         }
12927         else if (r_showsurfaces.integer == 4)
12928         {
12929                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12930                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12931                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12932                 {
12933                         unsigned char c = vi << 3;
12934                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12935                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12936                 }
12937                 R_Mesh_PrepareVertices_Generic_Unlock();
12938                 RSurf_DrawBatch();
12939         }
12940         else if (r_showsurfaces.integer == 2)
12941         {
12942                 const int *e;
12943                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12944                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12945                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12946                 {
12947                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12948                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12949                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12950                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12951                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12952                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12953                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12954                 }
12955                 R_Mesh_PrepareVertices_Generic_Unlock();
12956                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12957         }
12958         else
12959         {
12960                 int texturesurfaceindex;
12961                 int k;
12962                 const msurface_t *surface;
12963                 unsigned char surfacecolor4ub[4];
12964                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12965                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12966                 vi = 0;
12967                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12968                 {
12969                         surface = texturesurfacelist[texturesurfaceindex];
12970                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12971                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12972                         for (j = 0;j < surface->num_vertices;j++)
12973                         {
12974                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12975                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12976                                 vi++;
12977                         }
12978                 }
12979                 R_Mesh_PrepareVertices_Generic_Unlock();
12980                 RSurf_DrawBatch();
12981         }
12982 }
12983
12984 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12985 {
12986         CHECKGLERROR
12987         RSurf_SetupDepthAndCulling();
12988         if (r_showsurfaces.integer)
12989         {
12990                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12991                 return;
12992         }
12993         switch (vid.renderpath)
12994         {
12995         case RENDERPATH_GL20:
12996         case RENDERPATH_CGGL:
12997         case RENDERPATH_D3D9:
12998         case RENDERPATH_D3D10:
12999         case RENDERPATH_D3D11:
13000                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13001                 break;
13002         case RENDERPATH_GL13:
13003                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13004                 break;
13005         case RENDERPATH_GL11:
13006                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13007                 break;
13008         }
13009         CHECKGLERROR
13010 }
13011
13012 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13013 {
13014         CHECKGLERROR
13015         RSurf_SetupDepthAndCulling();
13016         if (r_showsurfaces.integer)
13017         {
13018                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13019                 return;
13020         }
13021         switch (vid.renderpath)
13022         {
13023         case RENDERPATH_GL20:
13024         case RENDERPATH_CGGL:
13025         case RENDERPATH_D3D9:
13026         case RENDERPATH_D3D10:
13027         case RENDERPATH_D3D11:
13028                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13029                 break;
13030         case RENDERPATH_GL13:
13031                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13032                 break;
13033         case RENDERPATH_GL11:
13034                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13035                 break;
13036         }
13037         CHECKGLERROR
13038 }
13039
13040 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13041 {
13042         int i, j;
13043         int texturenumsurfaces, endsurface;
13044         texture_t *texture;
13045         const msurface_t *surface;
13046 #define MAXBATCH_TRANSPARENTSURFACES 256
13047         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13048
13049         // if the model is static it doesn't matter what value we give for
13050         // wantnormals and wanttangents, so this logic uses only rules applicable
13051         // to a model, knowing that they are meaningless otherwise
13052         if (ent == r_refdef.scene.worldentity)
13053                 RSurf_ActiveWorldEntity();
13054         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13055                 RSurf_ActiveModelEntity(ent, false, false, false);
13056         else
13057         {
13058                 switch (vid.renderpath)
13059                 {
13060                 case RENDERPATH_GL20:
13061                 case RENDERPATH_CGGL:
13062                 case RENDERPATH_D3D9:
13063                 case RENDERPATH_D3D10:
13064                 case RENDERPATH_D3D11:
13065                         RSurf_ActiveModelEntity(ent, true, true, false);
13066                         break;
13067                 case RENDERPATH_GL13:
13068                 case RENDERPATH_GL11:
13069                         RSurf_ActiveModelEntity(ent, true, false, false);
13070                         break;
13071                 }
13072         }
13073
13074         if (r_transparentdepthmasking.integer)
13075         {
13076                 qboolean setup = false;
13077                 for (i = 0;i < numsurfaces;i = j)
13078                 {
13079                         j = i + 1;
13080                         surface = rsurface.modelsurfaces + surfacelist[i];
13081                         texture = surface->texture;
13082                         rsurface.texture = R_GetCurrentTexture(texture);
13083                         rsurface.lightmaptexture = NULL;
13084                         rsurface.deluxemaptexture = NULL;
13085                         rsurface.uselightmaptexture = false;
13086                         // scan ahead until we find a different texture
13087                         endsurface = min(i + 1024, numsurfaces);
13088                         texturenumsurfaces = 0;
13089                         texturesurfacelist[texturenumsurfaces++] = surface;
13090                         for (;j < endsurface;j++)
13091                         {
13092                                 surface = rsurface.modelsurfaces + surfacelist[j];
13093                                 if (texture != surface->texture)
13094                                         break;
13095                                 texturesurfacelist[texturenumsurfaces++] = surface;
13096                         }
13097                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13098                                 continue;
13099                         // render the range of surfaces as depth
13100                         if (!setup)
13101                         {
13102                                 setup = true;
13103                                 GL_ColorMask(0,0,0,0);
13104                                 GL_Color(1,1,1,1);
13105                                 GL_DepthTest(true);
13106                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13107                                 GL_DepthMask(true);
13108                                 GL_AlphaTest(false);
13109                                 R_Mesh_ResetTextureState();
13110                                 R_SetupShader_DepthOrShadow();
13111                         }
13112                         RSurf_SetupDepthAndCulling();
13113                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13114                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13115                         RSurf_DrawBatch();
13116                 }
13117                 if (setup)
13118                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13119         }
13120
13121         for (i = 0;i < numsurfaces;i = j)
13122         {
13123                 j = i + 1;
13124                 surface = rsurface.modelsurfaces + surfacelist[i];
13125                 texture = surface->texture;
13126                 rsurface.texture = R_GetCurrentTexture(texture);
13127                 // scan ahead until we find a different texture
13128                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13129                 texturenumsurfaces = 0;
13130                 texturesurfacelist[texturenumsurfaces++] = surface;
13131                 if(FAKELIGHT_ENABLED)
13132                 {
13133                         rsurface.lightmaptexture = NULL;
13134                         rsurface.deluxemaptexture = NULL;
13135                         rsurface.uselightmaptexture = false;
13136                         for (;j < endsurface;j++)
13137                         {
13138                                 surface = rsurface.modelsurfaces + surfacelist[j];
13139                                 if (texture != surface->texture)
13140                                         break;
13141                                 texturesurfacelist[texturenumsurfaces++] = surface;
13142                         }
13143                 }
13144                 else
13145                 {
13146                         rsurface.lightmaptexture = surface->lightmaptexture;
13147                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13148                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13149                         for (;j < endsurface;j++)
13150                         {
13151                                 surface = rsurface.modelsurfaces + surfacelist[j];
13152                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13153                                         break;
13154                                 texturesurfacelist[texturenumsurfaces++] = surface;
13155                         }
13156                 }
13157                 // render the range of surfaces
13158                 if (ent == r_refdef.scene.worldentity)
13159                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13160                 else
13161                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13162         }
13163         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13164         GL_AlphaTest(false);
13165 }
13166
13167 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13168 {
13169         // transparent surfaces get pushed off into the transparent queue
13170         int surfacelistindex;
13171         const msurface_t *surface;
13172         vec3_t tempcenter, center;
13173         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13174         {
13175                 surface = texturesurfacelist[surfacelistindex];
13176                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13177                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13178                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13179                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13180                 if (queueentity->transparent_offset) // transparent offset
13181                 {
13182                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13183                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13184                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13185                 }
13186                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13187         }
13188 }
13189
13190 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13191 {
13192         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13193                 return;
13194         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13195                 return;
13196         RSurf_SetupDepthAndCulling();
13197         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13198         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13199         RSurf_DrawBatch();
13200 }
13201
13202 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13203 {
13204         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13205         CHECKGLERROR
13206         if (depthonly)
13207                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13208         else if (prepass)
13209         {
13210                 if (!rsurface.texture->currentnumlayers)
13211                         return;
13212                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13213                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13214                 else
13215                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13216         }
13217         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13218                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13219         else if (!rsurface.texture->currentnumlayers)
13220                 return;
13221         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13222         {
13223                 // in the deferred case, transparent surfaces were queued during prepass
13224                 if (!r_shadow_usingdeferredprepass)
13225                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13226         }
13227         else
13228         {
13229                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13230                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13231         }
13232         CHECKGLERROR
13233 }
13234
13235 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13236 {
13237         int i, j;
13238         texture_t *texture;
13239         // break the surface list down into batches by texture and use of lightmapping
13240         for (i = 0;i < numsurfaces;i = j)
13241         {
13242                 j = i + 1;
13243                 // texture is the base texture pointer, rsurface.texture is the
13244                 // current frame/skin the texture is directing us to use (for example
13245                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13246                 // use skin 1 instead)
13247                 texture = surfacelist[i]->texture;
13248                 rsurface.texture = R_GetCurrentTexture(texture);
13249                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13250                 {
13251                         // if this texture is not the kind we want, skip ahead to the next one
13252                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13253                                 ;
13254                         continue;
13255                 }
13256                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13257                 {
13258                         rsurface.lightmaptexture = NULL;
13259                         rsurface.deluxemaptexture = NULL;
13260                         rsurface.uselightmaptexture = false;
13261                         // simply scan ahead until we find a different texture or lightmap state
13262                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13263                                 ;
13264                 }
13265                 else
13266                 {
13267                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13268                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13269                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13270                         // simply scan ahead until we find a different texture or lightmap state
13271                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13272                                 ;
13273                 }
13274                 // render the range of surfaces
13275                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13276         }
13277 }
13278
13279 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13280 {
13281         CHECKGLERROR
13282         if (depthonly)
13283                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13284         else if (prepass)
13285         {
13286                 if (!rsurface.texture->currentnumlayers)
13287                         return;
13288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13289                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13290                 else
13291                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13292         }
13293         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13294                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13295         else if (!rsurface.texture->currentnumlayers)
13296                 return;
13297         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13298         {
13299                 // in the deferred case, transparent surfaces were queued during prepass
13300                 if (!r_shadow_usingdeferredprepass)
13301                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13302         }
13303         else
13304         {
13305                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13306                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13307         }
13308         CHECKGLERROR
13309 }
13310
13311 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13312 {
13313         int i, j;
13314         texture_t *texture;
13315         // break the surface list down into batches by texture and use of lightmapping
13316         for (i = 0;i < numsurfaces;i = j)
13317         {
13318                 j = i + 1;
13319                 // texture is the base texture pointer, rsurface.texture is the
13320                 // current frame/skin the texture is directing us to use (for example
13321                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13322                 // use skin 1 instead)
13323                 texture = surfacelist[i]->texture;
13324                 rsurface.texture = R_GetCurrentTexture(texture);
13325                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13326                 {
13327                         // if this texture is not the kind we want, skip ahead to the next one
13328                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13329                                 ;
13330                         continue;
13331                 }
13332                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13333                 {
13334                         rsurface.lightmaptexture = NULL;
13335                         rsurface.deluxemaptexture = NULL;
13336                         rsurface.uselightmaptexture = false;
13337                         // simply scan ahead until we find a different texture or lightmap state
13338                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13339                                 ;
13340                 }
13341                 else
13342                 {
13343                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13344                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13345                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13346                         // simply scan ahead until we find a different texture or lightmap state
13347                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13348                                 ;
13349                 }
13350                 // render the range of surfaces
13351                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13352         }
13353 }
13354
13355 float locboxvertex3f[6*4*3] =
13356 {
13357         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13358         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13359         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13360         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13361         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13362         1,0,0, 0,0,0, 0,1,0, 1,1,0
13363 };
13364
13365 unsigned short locboxelements[6*2*3] =
13366 {
13367          0, 1, 2, 0, 2, 3,
13368          4, 5, 6, 4, 6, 7,
13369          8, 9,10, 8,10,11,
13370         12,13,14, 12,14,15,
13371         16,17,18, 16,18,19,
13372         20,21,22, 20,22,23
13373 };
13374
13375 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13376 {
13377         int i, j;
13378         cl_locnode_t *loc = (cl_locnode_t *)ent;
13379         vec3_t mins, size;
13380         float vertex3f[6*4*3];
13381         CHECKGLERROR
13382         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13383         GL_DepthMask(false);
13384         GL_DepthRange(0, 1);
13385         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13386         GL_DepthTest(true);
13387         GL_CullFace(GL_NONE);
13388         R_EntityMatrix(&identitymatrix);
13389
13390         R_Mesh_ResetTextureState();
13391
13392         i = surfacelist[0];
13393         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13394                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13395                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13396                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13397
13398         if (VectorCompare(loc->mins, loc->maxs))
13399         {
13400                 VectorSet(size, 2, 2, 2);
13401                 VectorMA(loc->mins, -0.5f, size, mins);
13402         }
13403         else
13404         {
13405                 VectorCopy(loc->mins, mins);
13406                 VectorSubtract(loc->maxs, loc->mins, size);
13407         }
13408
13409         for (i = 0;i < 6*4*3;)
13410                 for (j = 0;j < 3;j++, i++)
13411                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13412
13413         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13414         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13415         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13416 }
13417
13418 void R_DrawLocs(void)
13419 {
13420         int index;
13421         cl_locnode_t *loc, *nearestloc;
13422         vec3_t center;
13423         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13424         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13425         {
13426                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13427                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13428         }
13429 }
13430
13431 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13432 {
13433         if (decalsystem->decals)
13434                 Mem_Free(decalsystem->decals);
13435         memset(decalsystem, 0, sizeof(*decalsystem));
13436 }
13437
13438 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)
13439 {
13440         tridecal_t *decal;
13441         tridecal_t *decals;
13442         int i;
13443
13444         // expand or initialize the system
13445         if (decalsystem->maxdecals <= decalsystem->numdecals)
13446         {
13447                 decalsystem_t old = *decalsystem;
13448                 qboolean useshortelements;
13449                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13450                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13451                 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)));
13452                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13453                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13454                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13455                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13456                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13457                 if (decalsystem->numdecals)
13458                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13459                 if (old.decals)
13460                         Mem_Free(old.decals);
13461                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13462                         decalsystem->element3i[i] = i;
13463                 if (useshortelements)
13464                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13465                                 decalsystem->element3s[i] = i;
13466         }
13467
13468         // grab a decal and search for another free slot for the next one
13469         decals = decalsystem->decals;
13470         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13471         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13472                 ;
13473         decalsystem->freedecal = i;
13474         if (decalsystem->numdecals <= i)
13475                 decalsystem->numdecals = i + 1;
13476
13477         // initialize the decal
13478         decal->lived = 0;
13479         decal->triangleindex = triangleindex;
13480         decal->surfaceindex = surfaceindex;
13481         decal->decalsequence = decalsequence;
13482         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13483         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13484         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13485         decal->color4ub[0][3] = 255;
13486         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13487         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13488         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13489         decal->color4ub[1][3] = 255;
13490         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13491         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13492         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13493         decal->color4ub[2][3] = 255;
13494         decal->vertex3f[0][0] = v0[0];
13495         decal->vertex3f[0][1] = v0[1];
13496         decal->vertex3f[0][2] = v0[2];
13497         decal->vertex3f[1][0] = v1[0];
13498         decal->vertex3f[1][1] = v1[1];
13499         decal->vertex3f[1][2] = v1[2];
13500         decal->vertex3f[2][0] = v2[0];
13501         decal->vertex3f[2][1] = v2[1];
13502         decal->vertex3f[2][2] = v2[2];
13503         decal->texcoord2f[0][0] = t0[0];
13504         decal->texcoord2f[0][1] = t0[1];
13505         decal->texcoord2f[1][0] = t1[0];
13506         decal->texcoord2f[1][1] = t1[1];
13507         decal->texcoord2f[2][0] = t2[0];
13508         decal->texcoord2f[2][1] = t2[1];
13509 }
13510
13511 extern cvar_t cl_decals_bias;
13512 extern cvar_t cl_decals_models;
13513 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13514 // baseparms, parms, temps
13515 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)
13516 {
13517         int cornerindex;
13518         int index;
13519         float v[9][3];
13520         const float *vertex3f;
13521         int numpoints;
13522         float points[2][9][3];
13523         float temp[3];
13524         float tc[9][2];
13525         float f;
13526         float c[9][4];
13527         const int *e;
13528
13529         e = rsurface.modelelement3i + 3*triangleindex;
13530
13531         vertex3f = rsurface.modelvertex3f;
13532
13533         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13534         {
13535                 index = 3*e[cornerindex];
13536                 VectorCopy(vertex3f + index, v[cornerindex]);
13537         }
13538         // cull backfaces
13539         //TriangleNormal(v[0], v[1], v[2], normal);
13540         //if (DotProduct(normal, localnormal) < 0.0f)
13541         //      continue;
13542         // clip by each of the box planes formed from the projection matrix
13543         // if anything survives, we emit the decal
13544         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]);
13545         if (numpoints < 3)
13546                 return;
13547         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]);
13548         if (numpoints < 3)
13549                 return;
13550         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]);
13551         if (numpoints < 3)
13552                 return;
13553         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]);
13554         if (numpoints < 3)
13555                 return;
13556         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]);
13557         if (numpoints < 3)
13558                 return;
13559         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]);
13560         if (numpoints < 3)
13561                 return;
13562         // some part of the triangle survived, so we have to accept it...
13563         if (dynamic)
13564         {
13565                 // dynamic always uses the original triangle
13566                 numpoints = 3;
13567                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13568                 {
13569                         index = 3*e[cornerindex];
13570                         VectorCopy(vertex3f + index, v[cornerindex]);
13571                 }
13572         }
13573         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13574         {
13575                 // convert vertex positions to texcoords
13576                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13577                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13578                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13579                 // calculate distance fade from the projection origin
13580                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13581                 f = bound(0.0f, f, 1.0f);
13582                 c[cornerindex][0] = r * f;
13583                 c[cornerindex][1] = g * f;
13584                 c[cornerindex][2] = b * f;
13585                 c[cornerindex][3] = 1.0f;
13586                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13587         }
13588         if (dynamic)
13589                 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);
13590         else
13591                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13592                         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);
13593 }
13594 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)
13595 {
13596         matrix4x4_t projection;
13597         decalsystem_t *decalsystem;
13598         qboolean dynamic;
13599         dp_model_t *model;
13600         const msurface_t *surface;
13601         const msurface_t *surfaces;
13602         const int *surfacelist;
13603         const texture_t *texture;
13604         int numtriangles;
13605         int numsurfacelist;
13606         int surfacelistindex;
13607         int surfaceindex;
13608         int triangleindex;
13609         float localorigin[3];
13610         float localnormal[3];
13611         float localmins[3];
13612         float localmaxs[3];
13613         float localsize;
13614         //float normal[3];
13615         float planes[6][4];
13616         float angles[3];
13617         bih_t *bih;
13618         int bih_triangles_count;
13619         int bih_triangles[256];
13620         int bih_surfaces[256];
13621
13622         decalsystem = &ent->decalsystem;
13623         model = ent->model;
13624         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13625         {
13626                 R_DecalSystem_Reset(&ent->decalsystem);
13627                 return;
13628         }
13629
13630         if (!model->brush.data_leafs && !cl_decals_models.integer)
13631         {
13632                 if (decalsystem->model)
13633                         R_DecalSystem_Reset(decalsystem);
13634                 return;
13635         }
13636
13637         if (decalsystem->model != model)
13638                 R_DecalSystem_Reset(decalsystem);
13639         decalsystem->model = model;
13640
13641         RSurf_ActiveModelEntity(ent, false, false, false);
13642
13643         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13644         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13645         VectorNormalize(localnormal);
13646         localsize = worldsize*rsurface.inversematrixscale;
13647         localmins[0] = localorigin[0] - localsize;
13648         localmins[1] = localorigin[1] - localsize;
13649         localmins[2] = localorigin[2] - localsize;
13650         localmaxs[0] = localorigin[0] + localsize;
13651         localmaxs[1] = localorigin[1] + localsize;
13652         localmaxs[2] = localorigin[2] + localsize;
13653
13654         //VectorCopy(localnormal, planes[4]);
13655         //VectorVectors(planes[4], planes[2], planes[0]);
13656         AnglesFromVectors(angles, localnormal, NULL, false);
13657         AngleVectors(angles, planes[0], planes[2], planes[4]);
13658         VectorNegate(planes[0], planes[1]);
13659         VectorNegate(planes[2], planes[3]);
13660         VectorNegate(planes[4], planes[5]);
13661         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13662         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13663         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13664         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13665         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13666         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13667
13668 #if 1
13669 // works
13670 {
13671         matrix4x4_t forwardprojection;
13672         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13673         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13674 }
13675 #else
13676 // broken
13677 {
13678         float projectionvector[4][3];
13679         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13680         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13681         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13682         projectionvector[0][0] = planes[0][0] * ilocalsize;
13683         projectionvector[0][1] = planes[1][0] * ilocalsize;
13684         projectionvector[0][2] = planes[2][0] * ilocalsize;
13685         projectionvector[1][0] = planes[0][1] * ilocalsize;
13686         projectionvector[1][1] = planes[1][1] * ilocalsize;
13687         projectionvector[1][2] = planes[2][1] * ilocalsize;
13688         projectionvector[2][0] = planes[0][2] * ilocalsize;
13689         projectionvector[2][1] = planes[1][2] * ilocalsize;
13690         projectionvector[2][2] = planes[2][2] * ilocalsize;
13691         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13692         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13693         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13694         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13695 }
13696 #endif
13697
13698         dynamic = model->surfmesh.isanimated;
13699         numsurfacelist = model->nummodelsurfaces;
13700         surfacelist = model->sortedmodelsurfaces;
13701         surfaces = model->data_surfaces;
13702
13703         bih = NULL;
13704         bih_triangles_count = -1;
13705         if(!dynamic)
13706         {
13707                 if(model->render_bih.numleafs)
13708                         bih = &model->render_bih;
13709                 else if(model->collision_bih.numleafs)
13710                         bih = &model->collision_bih;
13711         }
13712         if(bih)
13713                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13714         if(bih_triangles_count == 0)
13715                 return;
13716         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13717                 return;
13718         if(bih_triangles_count > 0)
13719         {
13720                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13721                 {
13722                         surfaceindex = bih_surfaces[triangleindex];
13723                         surface = surfaces + surfaceindex;
13724                         texture = surface->texture;
13725                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13726                                 continue;
13727                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13728                                 continue;
13729                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13730                 }
13731         }
13732         else
13733         {
13734                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13735                 {
13736                         surfaceindex = surfacelist[surfacelistindex];
13737                         surface = surfaces + surfaceindex;
13738                         // check cull box first because it rejects more than any other check
13739                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13740                                 continue;
13741                         // skip transparent surfaces
13742                         texture = surface->texture;
13743                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13744                                 continue;
13745                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13746                                 continue;
13747                         numtriangles = surface->num_triangles;
13748                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13749                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13750                 }
13751         }
13752 }
13753
13754 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13755 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)
13756 {
13757         int renderentityindex;
13758         float worldmins[3];
13759         float worldmaxs[3];
13760         entity_render_t *ent;
13761
13762         if (!cl_decals_newsystem.integer)
13763                 return;
13764
13765         worldmins[0] = worldorigin[0] - worldsize;
13766         worldmins[1] = worldorigin[1] - worldsize;
13767         worldmins[2] = worldorigin[2] - worldsize;
13768         worldmaxs[0] = worldorigin[0] + worldsize;
13769         worldmaxs[1] = worldorigin[1] + worldsize;
13770         worldmaxs[2] = worldorigin[2] + worldsize;
13771
13772         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13773
13774         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13775         {
13776                 ent = r_refdef.scene.entities[renderentityindex];
13777                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13778                         continue;
13779
13780                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13781         }
13782 }
13783
13784 typedef struct r_decalsystem_splatqueue_s
13785 {
13786         vec3_t worldorigin;
13787         vec3_t worldnormal;
13788         float color[4];
13789         float tcrange[4];
13790         float worldsize;
13791         int decalsequence;
13792 }
13793 r_decalsystem_splatqueue_t;
13794
13795 int r_decalsystem_numqueued = 0;
13796 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13797
13798 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)
13799 {
13800         r_decalsystem_splatqueue_t *queue;
13801
13802         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13803                 return;
13804
13805         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13806         VectorCopy(worldorigin, queue->worldorigin);
13807         VectorCopy(worldnormal, queue->worldnormal);
13808         Vector4Set(queue->color, r, g, b, a);
13809         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13810         queue->worldsize = worldsize;
13811         queue->decalsequence = cl.decalsequence++;
13812 }
13813
13814 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13815 {
13816         int i;
13817         r_decalsystem_splatqueue_t *queue;
13818
13819         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13820                 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);
13821         r_decalsystem_numqueued = 0;
13822 }
13823
13824 extern cvar_t cl_decals_max;
13825 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13826 {
13827         int i;
13828         decalsystem_t *decalsystem = &ent->decalsystem;
13829         int numdecals;
13830         int killsequence;
13831         tridecal_t *decal;
13832         float frametime;
13833         float lifetime;
13834
13835         if (!decalsystem->numdecals)
13836                 return;
13837
13838         if (r_showsurfaces.integer)
13839                 return;
13840
13841         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13842         {
13843                 R_DecalSystem_Reset(decalsystem);
13844                 return;
13845         }
13846
13847         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13848         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13849
13850         if (decalsystem->lastupdatetime)
13851                 frametime = (cl.time - decalsystem->lastupdatetime);
13852         else
13853                 frametime = 0;
13854         decalsystem->lastupdatetime = cl.time;
13855         decal = decalsystem->decals;
13856         numdecals = decalsystem->numdecals;
13857
13858         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13859         {
13860                 if (decal->color4ub[0][3])
13861                 {
13862                         decal->lived += frametime;
13863                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13864                         {
13865                                 memset(decal, 0, sizeof(*decal));
13866                                 if (decalsystem->freedecal > i)
13867                                         decalsystem->freedecal = i;
13868                         }
13869                 }
13870         }
13871         decal = decalsystem->decals;
13872         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13873                 numdecals--;
13874
13875         // collapse the array by shuffling the tail decals into the gaps
13876         for (;;)
13877         {
13878                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13879                         decalsystem->freedecal++;
13880                 if (decalsystem->freedecal == numdecals)
13881                         break;
13882                 decal[decalsystem->freedecal] = decal[--numdecals];
13883         }
13884
13885         decalsystem->numdecals = numdecals;
13886
13887         if (numdecals <= 0)
13888         {
13889                 // if there are no decals left, reset decalsystem
13890                 R_DecalSystem_Reset(decalsystem);
13891         }
13892 }
13893
13894 extern skinframe_t *decalskinframe;
13895 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13896 {
13897         int i;
13898         decalsystem_t *decalsystem = &ent->decalsystem;
13899         int numdecals;
13900         tridecal_t *decal;
13901         float faderate;
13902         float alpha;
13903         float *v3f;
13904         float *c4f;
13905         float *t2f;
13906         const int *e;
13907         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13908         int numtris = 0;
13909
13910         numdecals = decalsystem->numdecals;
13911         if (!numdecals)
13912                 return;
13913
13914         if (r_showsurfaces.integer)
13915                 return;
13916
13917         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13918         {
13919                 R_DecalSystem_Reset(decalsystem);
13920                 return;
13921         }
13922
13923         // if the model is static it doesn't matter what value we give for
13924         // wantnormals and wanttangents, so this logic uses only rules applicable
13925         // to a model, knowing that they are meaningless otherwise
13926         if (ent == r_refdef.scene.worldentity)
13927                 RSurf_ActiveWorldEntity();
13928         else
13929                 RSurf_ActiveModelEntity(ent, false, false, false);
13930
13931         decalsystem->lastupdatetime = cl.time;
13932         decal = decalsystem->decals;
13933
13934         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13935
13936         // update vertex positions for animated models
13937         v3f = decalsystem->vertex3f;
13938         c4f = decalsystem->color4f;
13939         t2f = decalsystem->texcoord2f;
13940         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13941         {
13942                 if (!decal->color4ub[0][3])
13943                         continue;
13944
13945                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13946                         continue;
13947
13948                 // update color values for fading decals
13949                 if (decal->lived >= cl_decals_time.value)
13950                 {
13951                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13952                         alpha *= (1.0f/255.0f);
13953                 }
13954                 else
13955                         alpha = 1.0f/255.0f;
13956
13957                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13958                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13959                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13960                 c4f[ 3] = 1;
13961                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13962                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13963                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13964                 c4f[ 7] = 1;
13965                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13966                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13967                 c4f[10] = decal->color4ub[2][2] * alpha;
13968                 c4f[11] = 1;
13969
13970                 t2f[0] = decal->texcoord2f[0][0];
13971                 t2f[1] = decal->texcoord2f[0][1];
13972                 t2f[2] = decal->texcoord2f[1][0];
13973                 t2f[3] = decal->texcoord2f[1][1];
13974                 t2f[4] = decal->texcoord2f[2][0];
13975                 t2f[5] = decal->texcoord2f[2][1];
13976
13977                 // update vertex positions for animated models
13978                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13979                 {
13980                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13981                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13982                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13983                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13984                 }
13985                 else
13986                 {
13987                         VectorCopy(decal->vertex3f[0], v3f);
13988                         VectorCopy(decal->vertex3f[1], v3f + 3);
13989                         VectorCopy(decal->vertex3f[2], v3f + 6);
13990                 }
13991
13992                 if (r_refdef.fogenabled)
13993                 {
13994                         alpha = RSurf_FogVertex(v3f);
13995                         VectorScale(c4f, alpha, c4f);
13996                         alpha = RSurf_FogVertex(v3f + 3);
13997                         VectorScale(c4f + 4, alpha, c4f + 4);
13998                         alpha = RSurf_FogVertex(v3f + 6);
13999                         VectorScale(c4f + 8, alpha, c4f + 8);
14000                 }
14001
14002                 v3f += 9;
14003                 c4f += 12;
14004                 t2f += 6;
14005                 numtris++;
14006         }
14007
14008         if (numtris > 0)
14009         {
14010                 r_refdef.stats.drawndecals += numtris;
14011
14012                 // now render the decals all at once
14013                 // (this assumes they all use one particle font texture!)
14014                 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);
14015                 R_Mesh_ResetTextureState();
14016                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14017                 GL_DepthMask(false);
14018                 GL_DepthRange(0, 1);
14019                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14020                 GL_DepthTest(true);
14021                 GL_CullFace(GL_NONE);
14022                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14023                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14024                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14025         }
14026 }
14027
14028 static void R_DrawModelDecals(void)
14029 {
14030         int i, numdecals;
14031
14032         // fade faster when there are too many decals
14033         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14034         for (i = 0;i < r_refdef.scene.numentities;i++)
14035                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14036
14037         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14038         for (i = 0;i < r_refdef.scene.numentities;i++)
14039                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14040                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14041
14042         R_DecalSystem_ApplySplatEntitiesQueue();
14043
14044         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14045         for (i = 0;i < r_refdef.scene.numentities;i++)
14046                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14047
14048         r_refdef.stats.totaldecals += numdecals;
14049
14050         if (r_showsurfaces.integer)
14051                 return;
14052
14053         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14054
14055         for (i = 0;i < r_refdef.scene.numentities;i++)
14056         {
14057                 if (!r_refdef.viewcache.entityvisible[i])
14058                         continue;
14059                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14060                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14061         }
14062 }
14063
14064 extern cvar_t mod_collision_bih;
14065 void R_DrawDebugModel(void)
14066 {
14067         entity_render_t *ent = rsurface.entity;
14068         int i, j, k, l, flagsmask;
14069         const msurface_t *surface;
14070         dp_model_t *model = ent->model;
14071         vec3_t v;
14072
14073         switch(vid.renderpath)
14074         {
14075         case RENDERPATH_GL11:
14076         case RENDERPATH_GL13:
14077         case RENDERPATH_GL20:
14078         case RENDERPATH_CGGL:
14079                 break;
14080         case RENDERPATH_D3D9:
14081                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14082                 return;
14083         case RENDERPATH_D3D10:
14084                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14085                 return;
14086         case RENDERPATH_D3D11:
14087                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14088                 return;
14089         }
14090
14091         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14092
14093         R_Mesh_ResetTextureState();
14094         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14095         GL_DepthRange(0, 1);
14096         GL_DepthTest(!r_showdisabledepthtest.integer);
14097         GL_DepthMask(false);
14098         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14099
14100         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14101         {
14102                 int triangleindex;
14103                 int bihleafindex;
14104                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14105                 const q3mbrush_t *brush;
14106                 const bih_t *bih = &model->collision_bih;
14107                 const bih_leaf_t *bihleaf;
14108                 float vertex3f[3][3];
14109                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14110                 cullbox = false;
14111                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14112                 {
14113                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14114                                 continue;
14115                         switch (bihleaf->type)
14116                         {
14117                         case BIH_BRUSH:
14118                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14119                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14120                                 {
14121                                         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);
14122                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14123                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14124                                 }
14125                                 break;
14126                         case BIH_COLLISIONTRIANGLE:
14127                                 triangleindex = bihleaf->itemindex;
14128                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14129                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14130                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14131                                 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);
14132                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14133                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14134                                 break;
14135                         case BIH_RENDERTRIANGLE:
14136                                 triangleindex = bihleaf->itemindex;
14137                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14138                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14139                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14140                                 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);
14141                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14142                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14143                                 break;
14144                         }
14145                 }
14146         }
14147
14148         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14149
14150         if (r_showtris.integer || r_shownormals.integer)
14151         {
14152                 if (r_showdisabledepthtest.integer)
14153                 {
14154                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14155                         GL_DepthMask(false);
14156                 }
14157                 else
14158                 {
14159                         GL_BlendFunc(GL_ONE, GL_ZERO);
14160                         GL_DepthMask(true);
14161                 }
14162                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14163                 {
14164                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14165                                 continue;
14166                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14167                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14168                         {
14169                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14170                                 if (r_showtris.value > 0)
14171                                 {
14172                                         if (!rsurface.texture->currentlayers->depthmask)
14173                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14174                                         else if (ent == r_refdef.scene.worldentity)
14175                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14176                                         else
14177                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14178                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14179                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14180                                         RSurf_DrawBatch();
14181                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14182                                         CHECKGLERROR
14183                                 }
14184                                 if (r_shownormals.value < 0)
14185                                 {
14186                                         qglBegin(GL_LINES);
14187                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14188                                         {
14189                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14190                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14191                                                 qglVertex3f(v[0], v[1], v[2]);
14192                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14193                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14194                                                 qglVertex3f(v[0], v[1], v[2]);
14195                                         }
14196                                         qglEnd();
14197                                         CHECKGLERROR
14198                                 }
14199                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14200                                 {
14201                                         qglBegin(GL_LINES);
14202                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14203                                         {
14204                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14205                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14206                                                 qglVertex3f(v[0], v[1], v[2]);
14207                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14208                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14209                                                 qglVertex3f(v[0], v[1], v[2]);
14210                                         }
14211                                         qglEnd();
14212                                         CHECKGLERROR
14213                                         qglBegin(GL_LINES);
14214                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14215                                         {
14216                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14217                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14218                                                 qglVertex3f(v[0], v[1], v[2]);
14219                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14220                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14221                                                 qglVertex3f(v[0], v[1], v[2]);
14222                                         }
14223                                         qglEnd();
14224                                         CHECKGLERROR
14225                                         qglBegin(GL_LINES);
14226                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14227                                         {
14228                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14229                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14230                                                 qglVertex3f(v[0], v[1], v[2]);
14231                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14232                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14233                                                 qglVertex3f(v[0], v[1], v[2]);
14234                                         }
14235                                         qglEnd();
14236                                         CHECKGLERROR
14237                                 }
14238                         }
14239                 }
14240                 rsurface.texture = NULL;
14241         }
14242 }
14243
14244 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14245 int r_maxsurfacelist = 0;
14246 const msurface_t **r_surfacelist = NULL;
14247 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14248 {
14249         int i, j, endj, flagsmask;
14250         dp_model_t *model = r_refdef.scene.worldmodel;
14251         msurface_t *surfaces;
14252         unsigned char *update;
14253         int numsurfacelist = 0;
14254         if (model == NULL)
14255                 return;
14256
14257         if (r_maxsurfacelist < model->num_surfaces)
14258         {
14259                 r_maxsurfacelist = model->num_surfaces;
14260                 if (r_surfacelist)
14261                         Mem_Free((msurface_t**)r_surfacelist);
14262                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14263         }
14264
14265         RSurf_ActiveWorldEntity();
14266
14267         surfaces = model->data_surfaces;
14268         update = model->brushq1.lightmapupdateflags;
14269
14270         // update light styles on this submodel
14271         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14272         {
14273                 model_brush_lightstyleinfo_t *style;
14274                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14275                 {
14276                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14277                         {
14278                                 int *list = style->surfacelist;
14279                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14280                                 for (j = 0;j < style->numsurfaces;j++)
14281                                         update[list[j]] = true;
14282                         }
14283                 }
14284         }
14285
14286         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14287
14288         if (debug)
14289         {
14290                 R_DrawDebugModel();
14291                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14292                 return;
14293         }
14294
14295         rsurface.lightmaptexture = NULL;
14296         rsurface.deluxemaptexture = NULL;
14297         rsurface.uselightmaptexture = false;
14298         rsurface.texture = NULL;
14299         rsurface.rtlight = NULL;
14300         numsurfacelist = 0;
14301         // add visible surfaces to draw list
14302         for (i = 0;i < model->nummodelsurfaces;i++)
14303         {
14304                 j = model->sortedmodelsurfaces[i];
14305                 if (r_refdef.viewcache.world_surfacevisible[j])
14306                         r_surfacelist[numsurfacelist++] = surfaces + j;
14307         }
14308         // update lightmaps if needed
14309         if (model->brushq1.firstrender)
14310         {
14311                 model->brushq1.firstrender = false;
14312                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14313                         if (update[j])
14314                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14315         }
14316         else if (update)
14317         {
14318                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14319                         if (r_refdef.viewcache.world_surfacevisible[j])
14320                                 if (update[j])
14321                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14322         }
14323         // don't do anything if there were no surfaces
14324         if (!numsurfacelist)
14325         {
14326                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14327                 return;
14328         }
14329         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14330         GL_AlphaTest(false);
14331
14332         // add to stats if desired
14333         if (r_speeds.integer && !skysurfaces && !depthonly)
14334         {
14335                 r_refdef.stats.world_surfaces += numsurfacelist;
14336                 for (j = 0;j < numsurfacelist;j++)
14337                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14338         }
14339
14340         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14341 }
14342
14343 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14344 {
14345         int i, j, endj, flagsmask;
14346         dp_model_t *model = ent->model;
14347         msurface_t *surfaces;
14348         unsigned char *update;
14349         int numsurfacelist = 0;
14350         if (model == NULL)
14351                 return;
14352
14353         if (r_maxsurfacelist < model->num_surfaces)
14354         {
14355                 r_maxsurfacelist = model->num_surfaces;
14356                 if (r_surfacelist)
14357                         Mem_Free((msurface_t **)r_surfacelist);
14358                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14359         }
14360
14361         // if the model is static it doesn't matter what value we give for
14362         // wantnormals and wanttangents, so this logic uses only rules applicable
14363         // to a model, knowing that they are meaningless otherwise
14364         if (ent == r_refdef.scene.worldentity)
14365                 RSurf_ActiveWorldEntity();
14366         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14367                 RSurf_ActiveModelEntity(ent, false, false, false);
14368         else if (prepass)
14369                 RSurf_ActiveModelEntity(ent, true, true, true);
14370         else if (depthonly)
14371         {
14372                 switch (vid.renderpath)
14373                 {
14374                 case RENDERPATH_GL20:
14375                 case RENDERPATH_CGGL:
14376                 case RENDERPATH_D3D9:
14377                 case RENDERPATH_D3D10:
14378                 case RENDERPATH_D3D11:
14379                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14380                         break;
14381                 case RENDERPATH_GL13:
14382                 case RENDERPATH_GL11:
14383                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14384                         break;
14385                 }
14386         }
14387         else
14388         {
14389                 switch (vid.renderpath)
14390                 {
14391                 case RENDERPATH_GL20:
14392                 case RENDERPATH_CGGL:
14393                 case RENDERPATH_D3D9:
14394                 case RENDERPATH_D3D10:
14395                 case RENDERPATH_D3D11:
14396                         RSurf_ActiveModelEntity(ent, true, true, false);
14397                         break;
14398                 case RENDERPATH_GL13:
14399                 case RENDERPATH_GL11:
14400                         RSurf_ActiveModelEntity(ent, true, false, false);
14401                         break;
14402                 }
14403         }
14404
14405         surfaces = model->data_surfaces;
14406         update = model->brushq1.lightmapupdateflags;
14407
14408         // update light styles
14409         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14410         {
14411                 model_brush_lightstyleinfo_t *style;
14412                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14413                 {
14414                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14415                         {
14416                                 int *list = style->surfacelist;
14417                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14418                                 for (j = 0;j < style->numsurfaces;j++)
14419                                         update[list[j]] = true;
14420                         }
14421                 }
14422         }
14423
14424         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14425
14426         if (debug)
14427         {
14428                 R_DrawDebugModel();
14429                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14430                 return;
14431         }
14432
14433         rsurface.lightmaptexture = NULL;
14434         rsurface.deluxemaptexture = NULL;
14435         rsurface.uselightmaptexture = false;
14436         rsurface.texture = NULL;
14437         rsurface.rtlight = NULL;
14438         numsurfacelist = 0;
14439         // add visible surfaces to draw list
14440         for (i = 0;i < model->nummodelsurfaces;i++)
14441                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14442         // don't do anything if there were no surfaces
14443         if (!numsurfacelist)
14444         {
14445                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14446                 return;
14447         }
14448         // update lightmaps if needed
14449         if (update)
14450         {
14451                 int updated = 0;
14452                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14453                 {
14454                         if (update[j])
14455                         {
14456                                 updated++;
14457                                 R_BuildLightMap(ent, surfaces + j);
14458                         }
14459                 }
14460         }
14461         if (update)
14462                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14463                         if (update[j])
14464                                 R_BuildLightMap(ent, surfaces + j);
14465         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14466         GL_AlphaTest(false);
14467
14468         // add to stats if desired
14469         if (r_speeds.integer && !skysurfaces && !depthonly)
14470         {
14471                 r_refdef.stats.entities_surfaces += numsurfacelist;
14472                 for (j = 0;j < numsurfacelist;j++)
14473                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14474         }
14475
14476         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14477 }
14478
14479 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14480 {
14481         static texture_t texture;
14482         static msurface_t surface;
14483         const msurface_t *surfacelist = &surface;
14484
14485         // fake enough texture and surface state to render this geometry
14486
14487         texture.update_lastrenderframe = -1; // regenerate this texture
14488         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14489         texture.currentskinframe = skinframe;
14490         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14491         texture.offsetmapping = OFFSETMAPPING_OFF;
14492         texture.offsetscale = 1;
14493         texture.specularscalemod = 1;
14494         texture.specularpowermod = 1;
14495
14496         surface.texture = &texture;
14497         surface.num_triangles = numtriangles;
14498         surface.num_firsttriangle = firsttriangle;
14499         surface.num_vertices = numvertices;
14500         surface.num_firstvertex = firstvertex;
14501
14502         // now render it
14503         rsurface.texture = R_GetCurrentTexture(surface.texture);
14504         rsurface.lightmaptexture = NULL;
14505         rsurface.deluxemaptexture = NULL;
14506         rsurface.uselightmaptexture = false;
14507         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14508 }
14509
14510 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)
14511 {
14512         static msurface_t surface;
14513         const msurface_t *surfacelist = &surface;
14514
14515         // fake enough texture and surface state to render this geometry
14516         surface.texture = texture;
14517         surface.num_triangles = numtriangles;
14518         surface.num_firsttriangle = firsttriangle;
14519         surface.num_vertices = numvertices;
14520         surface.num_firstvertex = firstvertex;
14521
14522         // now render it
14523         rsurface.texture = R_GetCurrentTexture(surface.texture);
14524         rsurface.lightmaptexture = NULL;
14525         rsurface.deluxemaptexture = NULL;
14526         rsurface.uselightmaptexture = false;
14527         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14528 }