]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
626762f51ddc91735eeaaecdf1e3ce03200cb73e
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155
156 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
162
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
167
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
175
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
180
181 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
182
183 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
184
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
186
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194
195 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
196 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
197
198 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
199
200 extern cvar_t v_glslgamma;
201
202 extern qboolean v_flipped_state;
203
204 static struct r_bloomstate_s
205 {
206         qboolean enabled;
207         qboolean hdr;
208
209         int bloomwidth, bloomheight;
210
211         int screentexturewidth, screentextureheight;
212         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
213
214         int bloomtexturewidth, bloomtextureheight;
215         rtexture_t *texture_bloom;
216
217         // arrays for rendering the screen passes
218         float screentexcoord2f[8];
219         float bloomtexcoord2f[8];
220         float offsettexcoord2f[8];
221
222         r_viewport_t viewport;
223 }
224 r_bloomstate;
225
226 r_waterstate_t r_waterstate;
227
228 /// shadow volume bsp struct with automatically growing nodes buffer
229 svbsp_t r_svbsp;
230
231 rtexture_t *r_texture_blanknormalmap;
232 rtexture_t *r_texture_white;
233 rtexture_t *r_texture_grey128;
234 rtexture_t *r_texture_black;
235 rtexture_t *r_texture_notexture;
236 rtexture_t *r_texture_whitecube;
237 rtexture_t *r_texture_normalizationcube;
238 rtexture_t *r_texture_fogattenuation;
239 rtexture_t *r_texture_fogheighttexture;
240 rtexture_t *r_texture_gammaramps;
241 unsigned int r_texture_gammaramps_serial;
242 //rtexture_t *r_texture_fogintensity;
243 rtexture_t *r_texture_reflectcube;
244
245 // TODO: hash lookups?
246 typedef struct cubemapinfo_s
247 {
248         char basename[64];
249         rtexture_t *texture;
250 }
251 cubemapinfo_t;
252
253 int r_texture_numcubemaps;
254 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
255
256 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
257 unsigned int r_numqueries;
258 unsigned int r_maxqueries;
259
260 typedef struct r_qwskincache_s
261 {
262         char name[MAX_QPATH];
263         skinframe_t *skinframe;
264 }
265 r_qwskincache_t;
266
267 static r_qwskincache_t *r_qwskincache;
268 static int r_qwskincache_size;
269
270 /// vertex coordinates for a quad that covers the screen exactly
271 extern const float r_screenvertex3f[12];
272 extern const float r_d3dscreenvertex3f[12];
273 const float r_screenvertex3f[12] =
274 {
275         0, 0, 0,
276         1, 0, 0,
277         1, 1, 0,
278         0, 1, 0
279 };
280 const float r_d3dscreenvertex3f[12] =
281 {
282         0, 1, 0,
283         1, 1, 0,
284         1, 0, 0,
285         0, 0, 0
286 };
287
288 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
289 {
290         int i;
291         for (i = 0;i < verts;i++)
292         {
293                 out[0] = in[0] * r;
294                 out[1] = in[1] * g;
295                 out[2] = in[2] * b;
296                 out[3] = in[3];
297                 in += 4;
298                 out += 4;
299         }
300 }
301
302 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = r;
308                 out[1] = g;
309                 out[2] = b;
310                 out[3] = a;
311                 out += 4;
312         }
313 }
314
315 // FIXME: move this to client?
316 void FOG_clear(void)
317 {
318         if (gamemode == GAME_NEHAHRA)
319         {
320                 Cvar_Set("gl_fogenable", "0");
321                 Cvar_Set("gl_fogdensity", "0.2");
322                 Cvar_Set("gl_fogred", "0.3");
323                 Cvar_Set("gl_foggreen", "0.3");
324                 Cvar_Set("gl_fogblue", "0.3");
325         }
326         r_refdef.fog_density = 0;
327         r_refdef.fog_red = 0;
328         r_refdef.fog_green = 0;
329         r_refdef.fog_blue = 0;
330         r_refdef.fog_alpha = 1;
331         r_refdef.fog_start = 0;
332         r_refdef.fog_end = 16384;
333         r_refdef.fog_height = 1<<30;
334         r_refdef.fog_fadedepth = 128;
335         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
336 }
337
338 static void R_BuildBlankTextures(void)
339 {
340         unsigned char data[4];
341         data[2] = 128; // normal X
342         data[1] = 128; // normal Y
343         data[0] = 255; // normal Z
344         data[3] = 128; // height
345         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346         data[0] = 255;
347         data[1] = 255;
348         data[2] = 255;
349         data[3] = 255;
350         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351         data[0] = 128;
352         data[1] = 128;
353         data[2] = 128;
354         data[3] = 255;
355         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 0;
357         data[1] = 0;
358         data[2] = 0;
359         data[3] = 255;
360         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 }
362
363 static void R_BuildNoTexture(void)
364 {
365         int x, y;
366         unsigned char pix[16][16][4];
367         // this makes a light grey/dark grey checkerboard texture
368         for (y = 0;y < 16;y++)
369         {
370                 for (x = 0;x < 16;x++)
371                 {
372                         if ((y < 8) ^ (x < 8))
373                         {
374                                 pix[y][x][0] = 128;
375                                 pix[y][x][1] = 128;
376                                 pix[y][x][2] = 128;
377                                 pix[y][x][3] = 255;
378                         }
379                         else
380                         {
381                                 pix[y][x][0] = 64;
382                                 pix[y][x][1] = 64;
383                                 pix[y][x][2] = 64;
384                                 pix[y][x][3] = 255;
385                         }
386                 }
387         }
388         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
389 }
390
391 static void R_BuildWhiteCube(void)
392 {
393         unsigned char data[6*1*1*4];
394         memset(data, 255, sizeof(data));
395         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNormalizationCube(void)
399 {
400         int x, y, side;
401         vec3_t v;
402         vec_t s, t, intensity;
403 #define NORMSIZE 64
404         unsigned char *data;
405         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
406         for (side = 0;side < 6;side++)
407         {
408                 for (y = 0;y < NORMSIZE;y++)
409                 {
410                         for (x = 0;x < NORMSIZE;x++)
411                         {
412                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
413                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
414                                 switch(side)
415                                 {
416                                 default:
417                                 case 0:
418                                         v[0] = 1;
419                                         v[1] = -t;
420                                         v[2] = -s;
421                                         break;
422                                 case 1:
423                                         v[0] = -1;
424                                         v[1] = -t;
425                                         v[2] = s;
426                                         break;
427                                 case 2:
428                                         v[0] = s;
429                                         v[1] = 1;
430                                         v[2] = t;
431                                         break;
432                                 case 3:
433                                         v[0] = s;
434                                         v[1] = -1;
435                                         v[2] = -t;
436                                         break;
437                                 case 4:
438                                         v[0] = s;
439                                         v[1] = -t;
440                                         v[2] = 1;
441                                         break;
442                                 case 5:
443                                         v[0] = -s;
444                                         v[1] = -t;
445                                         v[2] = -1;
446                                         break;
447                                 }
448                                 intensity = 127.0f / sqrt(DotProduct(v, v));
449                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
450                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
451                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
452                                 data[((side*64+y)*64+x)*4+3] = 255;
453                         }
454                 }
455         }
456         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
457         Mem_Free(data);
458 }
459
460 static void R_BuildFogTexture(void)
461 {
462         int x, b;
463 #define FOGWIDTH 256
464         unsigned char data1[FOGWIDTH][4];
465         //unsigned char data2[FOGWIDTH][4];
466         double d, r, alpha;
467
468         r_refdef.fogmasktable_start = r_refdef.fog_start;
469         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
470         r_refdef.fogmasktable_range = r_refdef.fogrange;
471         r_refdef.fogmasktable_density = r_refdef.fog_density;
472
473         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
474         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
475         {
476                 d = (x * r - r_refdef.fogmasktable_start);
477                 if(developer_extra.integer)
478                         Con_DPrintf("%f ", d);
479                 d = max(0, d);
480                 if (r_fog_exp2.integer)
481                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
482                 else
483                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
484                 if(developer_extra.integer)
485                         Con_DPrintf(" : %f ", alpha);
486                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
487                 if(developer_extra.integer)
488                         Con_DPrintf(" = %f\n", alpha);
489                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
490         }
491
492         for (x = 0;x < FOGWIDTH;x++)
493         {
494                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495                 data1[x][0] = b;
496                 data1[x][1] = b;
497                 data1[x][2] = b;
498                 data1[x][3] = 255;
499                 //data2[x][0] = 255 - b;
500                 //data2[x][1] = 255 - b;
501                 //data2[x][2] = 255 - b;
502                 //data2[x][3] = 255;
503         }
504         if (r_texture_fogattenuation)
505         {
506                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
507                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
508         }
509         else
510         {
511                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
513         }
514 }
515
516 static void R_BuildFogHeightTexture(void)
517 {
518         unsigned char *inpixels;
519         int size;
520         int x;
521         int y;
522         int j;
523         float c[4];
524         float f;
525         inpixels = NULL;
526         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
527         if (r_refdef.fogheighttexturename[0])
528                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
529         if (!inpixels)
530         {
531                 r_refdef.fog_height_tablesize = 0;
532                 if (r_texture_fogheighttexture)
533                         R_FreeTexture(r_texture_fogheighttexture);
534                 r_texture_fogheighttexture = NULL;
535                 if (r_refdef.fog_height_table2d)
536                         Mem_Free(r_refdef.fog_height_table2d);
537                 r_refdef.fog_height_table2d = NULL;
538                 if (r_refdef.fog_height_table1d)
539                         Mem_Free(r_refdef.fog_height_table1d);
540                 r_refdef.fog_height_table1d = NULL;
541                 return;
542         }
543         size = image_width;
544         r_refdef.fog_height_tablesize = size;
545         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
546         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
547         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
548         Mem_Free(inpixels);
549         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
550         // average fog color table accounting for every fog layer between a point
551         // and the camera.  (Note: attenuation is handled separately!)
552         for (y = 0;y < size;y++)
553         {
554                 for (x = 0;x < size;x++)
555                 {
556                         Vector4Clear(c);
557                         f = 0;
558                         if (x < y)
559                         {
560                                 for (j = x;j <= y;j++)
561                                 {
562                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
563                                         f++;
564                                 }
565                         }
566                         else
567                         {
568                                 for (j = x;j >= y;j--)
569                                 {
570                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571                                         f++;
572                                 }
573                         }
574                         f = 1.0f / f;
575                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
576                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
577                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
579                 }
580         }
581         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
582 }
583
584 //=======================================================================================================================================================
585
586 static const char *builtinshaderstring =
587 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
588 "// written by Forest 'LordHavoc' Hale\n"
589 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
590 "\n"
591 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
592 "# define USEFOG\n"
593 "#endif\n"
594 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
595 "#define USELIGHTMAP\n"
596 "#endif\n"
597 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
598 "#define USEEYEVECTOR\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESHADOWMAP2D\n"
602 "# ifdef GL_EXT_gpu_shader4\n"
603 "#   extension GL_EXT_gpu_shader4 : enable\n"
604 "# endif\n"
605 "# ifdef GL_ARB_texture_gather\n"
606 "#   extension GL_ARB_texture_gather : enable\n"
607 "# else\n"
608 "#   ifdef GL_AMD_texture_texture4\n"
609 "#     extension GL_AMD_texture_texture4 : enable\n"
610 "#   endif\n"
611 "# endif\n"
612 "#endif\n"
613 "\n"
614 "//#ifdef USESHADOWSAMPLER\n"
615 "//# extension GL_ARB_shadow : enable\n"
616 "//#endif\n"
617 "\n"
618 "//#ifdef __GLSL_CG_DATA_TYPES\n"
619 "//# define myhalf half\n"
620 "//# define myhalf2 half2\n"
621 "//# define myhalf3 half3\n"
622 "//# define myhalf4 half4\n"
623 "//#else\n"
624 "# define myhalf float\n"
625 "# define myhalf2 vec2\n"
626 "# define myhalf3 vec3\n"
627 "# define myhalf4 vec4\n"
628 "//#endif\n"
629 "\n"
630 "#ifdef VERTEX_SHADER\n"
631 "uniform mat4 ModelViewProjectionMatrix;\n"
632 "#endif\n"
633 "\n"
634 "#ifdef MODE_DEPTH_OR_SHADOW\n"
635 "#ifdef VERTEX_SHADER\n"
636 "void main(void)\n"
637 "{\n"
638 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
639 "}\n"
640 "#endif\n"
641 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "\n"
643 "\n"
644 "\n"
645 "\n"
646 "#ifdef MODE_SHOWDEPTH\n"
647 "#ifdef VERTEX_SHADER\n"
648 "void main(void)\n"
649 "{\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
652 "}\n"
653 "#endif\n"
654 "\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "void main(void)\n"
657 "{\n"
658 "       gl_FragColor = gl_Color;\n"
659 "}\n"
660 "#endif\n"
661 "#else // !MODE_SHOWDEPTH\n"
662 "\n"
663 "\n"
664 "\n"
665 "\n"
666 "#ifdef MODE_POSTPROCESS\n"
667 "varying vec2 TexCoord1;\n"
668 "varying vec2 TexCoord2;\n"
669 "\n"
670 "#ifdef VERTEX_SHADER\n"
671 "void main(void)\n"
672 "{\n"
673 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
674 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
675 "#ifdef USEBLOOM\n"
676 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "\n"
681 "#ifdef FRAGMENT_SHADER\n"
682 "uniform sampler2D Texture_First;\n"
683 "#ifdef USEBLOOM\n"
684 "uniform sampler2D Texture_Second;\n"
685 "uniform vec4 BloomColorSubtract;\n"
686 "#endif\n"
687 "#ifdef USEGAMMARAMPS\n"
688 "uniform sampler2D Texture_GammaRamps;\n"
689 "#endif\n"
690 "#ifdef USESATURATION\n"
691 "uniform float Saturation;\n"
692 "#endif\n"
693 "#ifdef USEVIEWTINT\n"
694 "uniform vec4 ViewTintColor;\n"
695 "#endif\n"
696 "//uncomment these if you want to use them:\n"
697 "uniform vec4 UserVec1;\n"
698 "uniform vec4 UserVec2;\n"
699 "// uniform vec4 UserVec3;\n"
700 "// uniform vec4 UserVec4;\n"
701 "// uniform float ClientTime;\n"
702 "uniform vec2 PixelSize;\n"
703 "void main(void)\n"
704 "{\n"
705 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
706 "#ifdef USEBLOOM\n"
707 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
708 "#endif\n"
709 "#ifdef USEVIEWTINT\n"
710 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
711 "#endif\n"
712 "\n"
713 "#ifdef USEPOSTPROCESSING\n"
714 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
715 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
716 "       float sobel = 1.0;\n"
717 "       // vec2 ts = textureSize(Texture_First, 0);\n"
718 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
719 "       vec2 px = PixelSize;\n"
720 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
722 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
725 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
726 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
727 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
728 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
729 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
730 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
731 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
732 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
733 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
734 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
735 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
736 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
737 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
738 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
739 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
740 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
741 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
742 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
743 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
744 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
751 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
752 "#endif\n"
753 "\n"
754 "#ifdef USESATURATION\n"
755 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
756 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
757 "       // 'vampire sight' effect, wheres red is compensated\n"
758 "       #ifdef SATURATION_REDCOMPENSATE\n"
759 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
760 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
761 "               gl_FragColor.r += rboost;\n"
762 "       #else\n"
763 "               // normal desaturation\n"
764 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
765 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
766 "       #endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USEGAMMARAMPS\n"
770 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
771 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
772 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
773 "#endif\n"
774 "}\n"
775 "#endif\n"
776 "#else // !MODE_POSTPROCESS\n"
777 "\n"
778 "\n"
779 "\n"
780 "\n"
781 "#ifdef MODE_GENERIC\n"
782 "#ifdef USEDIFFUSE\n"
783 "varying vec2 TexCoord1;\n"
784 "#endif\n"
785 "#ifdef USESPECULAR\n"
786 "varying vec2 TexCoord2;\n"
787 "#endif\n"
788 "#ifdef VERTEX_SHADER\n"
789 "void main(void)\n"
790 "{\n"
791 "       gl_FrontColor = gl_Color;\n"
792 "#ifdef USEDIFFUSE\n"
793 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
797 "#endif\n"
798 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
799 "}\n"
800 "#endif\n"
801 "\n"
802 "#ifdef FRAGMENT_SHADER\n"
803 "#ifdef USEDIFFUSE\n"
804 "uniform sampler2D Texture_First;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "uniform sampler2D Texture_Second;\n"
808 "#endif\n"
809 "\n"
810 "void main(void)\n"
811 "{\n"
812 "#ifdef USEVIEWTINT\n"
813 "       gl_FragColor = gl_Color;\n"
814 "#else\n"
815 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
816 "#endif\n"
817 "#ifdef USEDIFFUSE\n"
818 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
819 "#endif\n"
820 "\n"
821 "#ifdef USESPECULAR\n"
822 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
823 "# ifdef USECOLORMAPPING\n"
824 "       gl_FragColor *= tex2;\n"
825 "# endif\n"
826 "# ifdef USEGLOW\n"
827 "       gl_FragColor += tex2;\n"
828 "# endif\n"
829 "# ifdef USEVERTEXTEXTUREBLEND\n"
830 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
831 "# endif\n"
832 "#endif\n"
833 "}\n"
834 "#endif\n"
835 "#else // !MODE_GENERIC\n"
836 "\n"
837 "\n"
838 "\n"
839 "\n"
840 "#ifdef MODE_BLOOMBLUR\n"
841 "varying TexCoord;\n"
842 "#ifdef VERTEX_SHADER\n"
843 "void main(void)\n"
844 "{\n"
845 "       gl_FrontColor = gl_Color;\n"
846 "       TexCoord = gl_MultiTexCoord0.xy;\n"
847 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
848 "}\n"
849 "#endif\n"
850 "\n"
851 "#ifdef FRAGMENT_SHADER\n"
852 "uniform sampler2D Texture_First;\n"
853 "uniform vec4 BloomBlur_Parameters;\n"
854 "\n"
855 "void main(void)\n"
856 "{\n"
857 "       int i;\n"
858 "       vec2 tc = TexCoord;\n"
859 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
860 "       tc += BloomBlur_Parameters.xy;\n"
861 "       for (i = 1;i < SAMPLES;i++)\n"
862 "       {\n"
863 "               color += texture2D(Texture_First, tc).rgb;\n"
864 "               tc += BloomBlur_Parameters.xy;\n"
865 "       }\n"
866 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
867 "}\n"
868 "#endif\n"
869 "#else // !MODE_BLOOMBLUR\n"
870 "#ifdef MODE_REFRACTION\n"
871 "varying vec2 TexCoord;\n"
872 "varying vec4 ModelViewProjectionPosition;\n"
873 "uniform mat4 TexMatrix;\n"
874 "#ifdef VERTEX_SHADER\n"
875 "\n"
876 "void main(void)\n"
877 "{\n"
878 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
879 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
880 "       ModelViewProjectionPosition = gl_Position;\n"
881 "}\n"
882 "#endif\n"
883 "\n"
884 "#ifdef FRAGMENT_SHADER\n"
885 "uniform sampler2D Texture_Normal;\n"
886 "uniform sampler2D Texture_Refraction;\n"
887 "uniform sampler2D Texture_Reflection;\n"
888 "\n"
889 "uniform vec4 DistortScaleRefractReflect;\n"
890 "uniform vec4 ScreenScaleRefractReflect;\n"
891 "uniform vec4 ScreenCenterRefractReflect;\n"
892 "uniform vec4 RefractColor;\n"
893 "uniform vec4 ReflectColor;\n"
894 "uniform float ReflectFactor;\n"
895 "uniform float ReflectOffset;\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
900 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
901 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
902 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
903 "       // FIXME temporary hack to detect the case that the reflection\n"
904 "       // gets blackened at edges due to leaving the area that contains actual\n"
905 "       // content.\n"
906 "       // Remove this 'ack once we have a better way to stop this thing from\n"
907 "       // 'appening.\n"
908 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
909 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
910 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
912 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
913 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
914 "}\n"
915 "#endif\n"
916 "#else // !MODE_REFRACTION\n"
917 "\n"
918 "\n"
919 "\n"
920 "\n"
921 "#ifdef MODE_WATER\n"
922 "varying vec2 TexCoord;\n"
923 "varying vec3 EyeVector;\n"
924 "varying vec4 ModelViewProjectionPosition;\n"
925 "#ifdef VERTEX_SHADER\n"
926 "uniform vec3 EyePosition;\n"
927 "uniform mat4 TexMatrix;\n"
928 "\n"
929 "void main(void)\n"
930 "{\n"
931 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
932 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
933 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
934 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
935 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
936 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
937 "       ModelViewProjectionPosition = gl_Position;\n"
938 "}\n"
939 "#endif\n"
940 "\n"
941 "#ifdef FRAGMENT_SHADER\n"
942 "uniform sampler2D Texture_Normal;\n"
943 "uniform sampler2D Texture_Refraction;\n"
944 "uniform sampler2D Texture_Reflection;\n"
945 "\n"
946 "uniform vec4 DistortScaleRefractReflect;\n"
947 "uniform vec4 ScreenScaleRefractReflect;\n"
948 "uniform vec4 ScreenCenterRefractReflect;\n"
949 "uniform vec4 RefractColor;\n"
950 "uniform vec4 ReflectColor;\n"
951 "uniform float ReflectFactor;\n"
952 "uniform float ReflectOffset;\n"
953 "uniform float ClientTime;\n"
954 "#ifdef USENORMALMAPSCROLLBLEND\n"
955 "uniform vec2 NormalmapScrollBlend;\n"
956 "#endif\n"
957 "\n"
958 "void main(void)\n"
959 "{\n"
960 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
961 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
962 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
963 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
964 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
965 "       #ifdef USENORMALMAPSCROLLBLEND\n"
966 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
967 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
968 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
969 "       #else\n"
970 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
971 "       #endif\n"
972 "       // FIXME temporary hack to detect the case that the reflection\n"
973 "       // gets blackened at edges due to leaving the area that contains actual\n"
974 "       // content.\n"
975 "       // Remove this 'ack once we have a better way to stop this thing from\n"
976 "       // 'appening.\n"
977 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
978 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
979 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
980 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
981 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
982 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
983 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
984 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
985 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
986 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
987 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
988 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
989 "       gl_FragColor.a = f1 + 0.5;\n"
990 "}\n"
991 "#endif\n"
992 "#else // !MODE_WATER\n"
993 "\n"
994 "\n"
995 "\n"
996 "\n"
997 "// common definitions between vertex shader and fragment shader:\n"
998 "\n"
999 "varying vec2 TexCoord;\n"
1000 "#ifdef USEVERTEXTEXTUREBLEND\n"
1001 "varying vec2 TexCoord2;\n"
1002 "#endif\n"
1003 "#ifdef USELIGHTMAP\n"
1004 "varying vec2 TexCoordLightmap;\n"
1005 "#endif\n"
1006 "\n"
1007 "#ifdef MODE_LIGHTSOURCE\n"
1008 "varying vec3 CubeVector;\n"
1009 "#endif\n"
1010 "\n"
1011 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1012 "varying vec3 LightVector;\n"
1013 "#endif\n"
1014 "\n"
1015 "#ifdef USEEYEVECTOR\n"
1016 "varying vec3 EyeVector;\n"
1017 "#endif\n"
1018 "#ifdef USEFOG\n"
1019 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1020 "#endif\n"
1021 "\n"
1022 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1023 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1024 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1025 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1026 "#endif\n"
1027 "\n"
1028 "#ifdef USEREFLECTION\n"
1029 "varying vec4 ModelViewProjectionPosition;\n"
1030 "#endif\n"
1031 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1032 "uniform vec3 LightPosition;\n"
1033 "varying vec4 ModelViewPosition;\n"
1034 "#endif\n"
1035 "\n"
1036 "#ifdef MODE_LIGHTSOURCE\n"
1037 "uniform vec3 LightPosition;\n"
1038 "#endif\n"
1039 "uniform vec3 EyePosition;\n"
1040 "#ifdef MODE_LIGHTDIRECTION\n"
1041 "uniform vec3 LightDir;\n"
1042 "#endif\n"
1043 "uniform vec4 FogPlane;\n"
1044 "\n"
1045 "#ifdef USESHADOWMAPORTHO\n"
1046 "varying vec3 ShadowMapTC;\n"
1047 "#endif\n"
1048 "\n"
1049 "\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1054 "\n"
1055 "// fragment shader specific:\n"
1056 "#ifdef FRAGMENT_SHADER\n"
1057 "\n"
1058 "uniform sampler2D Texture_Normal;\n"
1059 "uniform sampler2D Texture_Color;\n"
1060 "uniform sampler2D Texture_Gloss;\n"
1061 "#ifdef USEGLOW\n"
1062 "uniform sampler2D Texture_Glow;\n"
1063 "#endif\n"
1064 "#ifdef USEVERTEXTEXTUREBLEND\n"
1065 "uniform sampler2D Texture_SecondaryNormal;\n"
1066 "uniform sampler2D Texture_SecondaryColor;\n"
1067 "uniform sampler2D Texture_SecondaryGloss;\n"
1068 "#ifdef USEGLOW\n"
1069 "uniform sampler2D Texture_SecondaryGlow;\n"
1070 "#endif\n"
1071 "#endif\n"
1072 "#ifdef USECOLORMAPPING\n"
1073 "uniform sampler2D Texture_Pants;\n"
1074 "uniform sampler2D Texture_Shirt;\n"
1075 "#endif\n"
1076 "#ifdef USEFOG\n"
1077 "#ifdef USEFOGHEIGHTTEXTURE\n"
1078 "uniform sampler2D Texture_FogHeightTexture;\n"
1079 "#endif\n"
1080 "uniform sampler2D Texture_FogMask;\n"
1081 "#endif\n"
1082 "#ifdef USELIGHTMAP\n"
1083 "uniform sampler2D Texture_Lightmap;\n"
1084 "#endif\n"
1085 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1086 "uniform sampler2D Texture_Deluxemap;\n"
1087 "#endif\n"
1088 "#ifdef USEREFLECTION\n"
1089 "uniform sampler2D Texture_Reflection;\n"
1090 "#endif\n"
1091 "\n"
1092 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1093 "uniform sampler2D Texture_ScreenDepth;\n"
1094 "uniform sampler2D Texture_ScreenNormalMap;\n"
1095 "#endif\n"
1096 "#ifdef USEDEFERREDLIGHTMAP\n"
1097 "uniform sampler2D Texture_ScreenDiffuse;\n"
1098 "uniform sampler2D Texture_ScreenSpecular;\n"
1099 "#endif\n"
1100 "\n"
1101 "uniform myhalf3 Color_Pants;\n"
1102 "uniform myhalf3 Color_Shirt;\n"
1103 "uniform myhalf3 FogColor;\n"
1104 "\n"
1105 "#ifdef USEFOG\n"
1106 "uniform float FogRangeRecip;\n"
1107 "uniform float FogPlaneViewDist;\n"
1108 "uniform float FogHeightFade;\n"
1109 "vec3 FogVertex(vec3 surfacecolor)\n"
1110 "{\n"
1111 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1112 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1113 "       float fogfrac;\n"
1114 "#ifdef USEFOGHEIGHTTEXTURE\n"
1115 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1116 "       fogfrac = fogheightpixel.a;\n"
1117 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1118 "#else\n"
1119 "# ifdef USEFOGOUTSIDE\n"
1120 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1121 "# else\n"
1122 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1123 "# endif\n"
1124 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1125 "#endif\n"
1126 "}\n"
1127 "#endif\n"
1128 "\n"
1129 "#ifdef USEOFFSETMAPPING\n"
1130 "uniform float OffsetMapping_Scale;\n"
1131 "vec2 OffsetMapping(vec2 TexCoord)\n"
1132 "{\n"
1133 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1134 "       // 14 sample relief mapping: linear search and then binary search\n"
1135 "       // this basically steps forward a small amount repeatedly until it finds\n"
1136 "       // itself inside solid, then jitters forward and back using decreasing\n"
1137 "       // amounts to find the impact\n"
1138 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1139 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1140 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1141 "       vec3 RT = vec3(TexCoord, 1);\n"
1142 "       OffsetVector *= 0.1;\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1153 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1157 "       return RT.xy;\n"
1158 "#else\n"
1159 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1160 "       // this basically moves forward the full distance, and then backs up based\n"
1161 "       // on height of samples\n"
1162 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1163 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1164 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1165 "       TexCoord += OffsetVector;\n"
1166 "       OffsetVector *= 0.5;\n"
1167 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1168 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1169 "       return TexCoord;\n"
1170 "#endif\n"
1171 "}\n"
1172 "#endif // USEOFFSETMAPPING\n"
1173 "\n"
1174 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1175 "uniform sampler2D Texture_Attenuation;\n"
1176 "uniform samplerCube Texture_Cube;\n"
1177 "#endif\n"
1178 "\n"
1179 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1180 "\n"
1181 "#ifdef USESHADOWMAP2D\n"
1182 "# ifdef USESHADOWSAMPLER\n"
1183 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1184 "# else\n"
1185 "uniform sampler2D Texture_ShadowMap2D;\n"
1186 "# endif\n"
1187 "#endif\n"
1188 "\n"
1189 "#ifdef USESHADOWMAPVSDCT\n"
1190 "uniform samplerCube Texture_CubeProjection;\n"
1191 "#endif\n"
1192 "\n"
1193 "#if defined(USESHADOWMAP2D)\n"
1194 "uniform vec2 ShadowMap_TextureScale;\n"
1195 "uniform vec4 ShadowMap_Parameters;\n"
1196 "#endif\n"
1197 "\n"
1198 "#if defined(USESHADOWMAP2D)\n"
1199 "# ifdef USESHADOWMAPORTHO\n"
1200 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1201 "# else\n"
1202 "#  ifdef USESHADOWMAPVSDCT\n"
1203 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1204 "{\n"
1205 "       vec3 adir = abs(dir);\n"
1206 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1207 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1208 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1209 "}\n"
1210 "#  else\n"
1211 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1212 "{\n"
1213 "       vec3 adir = abs(dir);\n"
1214 "       float ma = adir.z;\n"
1215 "       vec4 proj = vec4(dir, 2.5);\n"
1216 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1217 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1218 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1219 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1220 "}\n"
1221 "#  endif\n"
1222 "# endif\n"
1223 "#endif // defined(USESHADOWMAP2D)\n"
1224 "\n"
1225 "# ifdef USESHADOWMAP2D\n"
1226 "float ShadowMapCompare(vec3 dir)\n"
1227 "{\n"
1228 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1229 "       float f;\n"
1230 "\n"
1231 "#  ifdef USESHADOWSAMPLER\n"
1232 "#    ifdef USESHADOWMAPPCF\n"
1233 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1234 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1235 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1236 "#    else\n"
1237 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1238 "#    endif\n"
1239 "#  else\n"
1240 "#    ifdef USESHADOWMAPPCF\n"
1241 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1242 "#      ifdef GL_ARB_texture_gather\n"
1243 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1244 "#      else\n"
1245 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1246 "#      endif\n"
1247 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1248 "#      if USESHADOWMAPPCF > 1\n"
1249 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1250 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1251 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1252 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1253 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1254 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1255 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1256 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1257 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1258 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1259 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1260 "       locols.yz += group2.ab;\n"
1261 "       hicols.yz += group8.rg;\n"
1262 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1263 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1264 "                               mix(locols, hicols, offset.y);\n"
1265 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1266 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1267 "       f = dot(cols, vec4(1.0/25.0));\n"
1268 "#      else\n"
1269 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1270 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1271 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1272 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1273 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1274 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1275 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1276 "#      endif\n"
1277 "#     else\n"
1278 "#      ifdef GL_EXT_gpu_shader4\n"
1279 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1280 "#      else\n"
1281 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1282 "#      endif\n"
1283 "#      if USESHADOWMAPPCF > 1\n"
1284 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1285 "       center *= ShadowMap_TextureScale;\n"
1286 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1287 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1288 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1289 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1290 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1291 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1292 "#      else\n"
1293 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1294 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1295 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1296 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1297 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1298 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1299 "#      endif\n"
1300 "#     endif\n"
1301 "#    else\n"
1302 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1303 "#    endif\n"
1304 "#  endif\n"
1305 "#  ifdef USESHADOWMAPORTHO\n"
1306 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1307 "#  else\n"
1308 "       return f;\n"
1309 "#  endif\n"
1310 "}\n"
1311 "# endif\n"
1312 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1313 "#endif // FRAGMENT_SHADER\n"
1314 "\n"
1315 "\n"
1316 "\n"
1317 "\n"
1318 "#ifdef MODE_DEFERREDGEOMETRY\n"
1319 "#ifdef VERTEX_SHADER\n"
1320 "uniform mat4 TexMatrix;\n"
1321 "#ifdef USEVERTEXTEXTUREBLEND\n"
1322 "uniform mat4 BackgroundTexMatrix;\n"
1323 "#endif\n"
1324 "uniform mat4 ModelViewMatrix;\n"
1325 "void main(void)\n"
1326 "{\n"
1327 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       gl_FrontColor = gl_Color;\n"
1330 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1331 "#endif\n"
1332 "\n"
1333 "       // transform unnormalized eye direction into tangent space\n"
1334 "#ifdef USEOFFSETMAPPING\n"
1335 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1336 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1337 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1338 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1339 "#endif\n"
1340 "\n"
1341 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1342 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1343 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1344 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1345 "}\n"
1346 "#endif // VERTEX_SHADER\n"
1347 "\n"
1348 "#ifdef FRAGMENT_SHADER\n"
1349 "void main(void)\n"
1350 "{\n"
1351 "#ifdef USEOFFSETMAPPING\n"
1352 "       // apply offsetmapping\n"
1353 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1354 "#define TexCoord TexCoordOffset\n"
1355 "#endif\n"
1356 "\n"
1357 "#ifdef USEALPHAKILL\n"
1358 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1359 "               discard;\n"
1360 "#endif\n"
1361 "\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1364 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1365 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1366 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1367 "#endif\n"
1368 "\n"
1369 "#ifdef USEVERTEXTEXTUREBLEND\n"
1370 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1371 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1372 "#else\n"
1373 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1374 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1375 "#endif\n"
1376 "\n"
1377 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1378 "}\n"
1379 "#endif // FRAGMENT_SHADER\n"
1380 "#else // !MODE_DEFERREDGEOMETRY\n"
1381 "\n"
1382 "\n"
1383 "\n"
1384 "\n"
1385 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1386 "#ifdef VERTEX_SHADER\n"
1387 "uniform mat4 ModelViewMatrix;\n"
1388 "void main(void)\n"
1389 "{\n"
1390 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1391 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1392 "}\n"
1393 "#endif // VERTEX_SHADER\n"
1394 "\n"
1395 "#ifdef FRAGMENT_SHADER\n"
1396 "uniform mat4 ViewToLight;\n"
1397 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1398 "uniform vec2 ScreenToDepth;\n"
1399 "uniform myhalf3 DeferredColor_Ambient;\n"
1400 "uniform myhalf3 DeferredColor_Diffuse;\n"
1401 "#ifdef USESPECULAR\n"
1402 "uniform myhalf3 DeferredColor_Specular;\n"
1403 "uniform myhalf SpecularPower;\n"
1404 "#endif\n"
1405 "uniform myhalf2 PixelToScreenTexCoord;\n"
1406 "void main(void)\n"
1407 "{\n"
1408 "       // calculate viewspace pixel position\n"
1409 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1410 "       vec3 position;\n"
1411 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1412 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1413 "       // decode viewspace pixel normal\n"
1414 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1415 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1416 "       // surfacenormal = pixel normal in viewspace\n"
1417 "       // LightVector = pixel to light in viewspace\n"
1418 "       // CubeVector = position in lightspace\n"
1419 "       // eyevector = pixel to view in viewspace\n"
1420 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1421 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1422 "#ifdef USEDIFFUSE\n"
1423 "       // calculate diffuse shading\n"
1424 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1425 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1426 "#endif\n"
1427 "#ifdef USESPECULAR\n"
1428 "       // calculate directional shading\n"
1429 "       vec3 eyevector = position * -1.0;\n"
1430 "#  ifdef USEEXACTSPECULARMATH\n"
1431 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1432 "#  else\n"
1433 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1434 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1435 "#  endif\n"
1436 "#endif\n"
1437 "\n"
1438 "#if defined(USESHADOWMAP2D)\n"
1439 "       fade *= ShadowMapCompare(CubeVector);\n"
1440 "#endif\n"
1441 "\n"
1442 "#ifdef USEDIFFUSE\n"
1443 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1444 "#else\n"
1445 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1446 "#endif\n"
1447 "#ifdef USESPECULAR\n"
1448 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1449 "#else\n"
1450 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1451 "#endif\n"
1452 "\n"
1453 "# ifdef USECUBEFILTER\n"
1454 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1455 "       gl_FragData[0].rgb *= cubecolor;\n"
1456 "       gl_FragData[1].rgb *= cubecolor;\n"
1457 "# endif\n"
1458 "}\n"
1459 "#endif // FRAGMENT_SHADER\n"
1460 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1461 "\n"
1462 "\n"
1463 "\n"
1464 "\n"
1465 "#ifdef VERTEX_SHADER\n"
1466 "uniform mat4 TexMatrix;\n"
1467 "#ifdef USEVERTEXTEXTUREBLEND\n"
1468 "uniform mat4 BackgroundTexMatrix;\n"
1469 "#endif\n"
1470 "#ifdef MODE_LIGHTSOURCE\n"
1471 "uniform mat4 ModelToLight;\n"
1472 "#endif\n"
1473 "#ifdef USESHADOWMAPORTHO\n"
1474 "uniform mat4 ShadowMapMatrix;\n"
1475 "#endif\n"
1476 "void main(void)\n"
1477 "{\n"
1478 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1479 "       gl_FrontColor = gl_Color;\n"
1480 "#endif\n"
1481 "       // copy the surface texcoord\n"
1482 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1483 "#ifdef USEVERTEXTEXTUREBLEND\n"
1484 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1485 "#endif\n"
1486 "#ifdef USELIGHTMAP\n"
1487 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1488 "#endif\n"
1489 "\n"
1490 "#ifdef MODE_LIGHTSOURCE\n"
1491 "       // transform vertex position into light attenuation/cubemap space\n"
1492 "       // (-1 to +1 across the light box)\n"
1493 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1494 "\n"
1495 "# ifdef USEDIFFUSE\n"
1496 "       // transform unnormalized light direction into tangent space\n"
1497 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1498 "       //  normalize it per pixel)\n"
1499 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1500 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1501 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1502 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1503 "# endif\n"
1504 "#endif\n"
1505 "\n"
1506 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1507 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1508 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1509 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1510 "#endif\n"
1511 "\n"
1512 "       // transform unnormalized eye direction into tangent space\n"
1513 "#ifdef USEEYEVECTOR\n"
1514 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1515 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1516 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1517 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1518 "#endif\n"
1519 "\n"
1520 "#ifdef USEFOG\n"
1521 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1522 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1523 "#endif\n"
1524 "\n"
1525 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1526 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1527 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1528 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1529 "#endif\n"
1530 "\n"
1531 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1532 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1533 "\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1536 "#endif\n"
1537 "\n"
1538 "#ifdef USEREFLECTION\n"
1539 "       ModelViewProjectionPosition = gl_Position;\n"
1540 "#endif\n"
1541 "}\n"
1542 "#endif // VERTEX_SHADER\n"
1543 "\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "#ifdef FRAGMENT_SHADER\n"
1548 "#ifdef USEDEFERREDLIGHTMAP\n"
1549 "uniform myhalf2 PixelToScreenTexCoord;\n"
1550 "uniform myhalf3 DeferredMod_Diffuse;\n"
1551 "uniform myhalf3 DeferredMod_Specular;\n"
1552 "#endif\n"
1553 "uniform myhalf3 Color_Ambient;\n"
1554 "uniform myhalf3 Color_Diffuse;\n"
1555 "uniform myhalf3 Color_Specular;\n"
1556 "uniform myhalf SpecularPower;\n"
1557 "#ifdef USEGLOW\n"
1558 "uniform myhalf3 Color_Glow;\n"
1559 "#endif\n"
1560 "uniform myhalf Alpha;\n"
1561 "#ifdef USEREFLECTION\n"
1562 "uniform vec4 DistortScaleRefractReflect;\n"
1563 "uniform vec4 ScreenScaleRefractReflect;\n"
1564 "uniform vec4 ScreenCenterRefractReflect;\n"
1565 "uniform myhalf4 ReflectColor;\n"
1566 "#endif\n"
1567 "#ifdef USEREFLECTCUBE\n"
1568 "uniform mat4 ModelToReflectCube;\n"
1569 "uniform sampler2D Texture_ReflectMask;\n"
1570 "uniform samplerCube Texture_ReflectCube;\n"
1571 "#endif\n"
1572 "#ifdef MODE_LIGHTDIRECTION\n"
1573 "uniform myhalf3 LightColor;\n"
1574 "#endif\n"
1575 "#ifdef MODE_LIGHTSOURCE\n"
1576 "uniform myhalf3 LightColor;\n"
1577 "#endif\n"
1578 "void main(void)\n"
1579 "{\n"
1580 "#ifdef USEOFFSETMAPPING\n"
1581 "       // apply offsetmapping\n"
1582 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1583 "#define TexCoord TexCoordOffset\n"
1584 "#endif\n"
1585 "\n"
1586 "       // combine the diffuse textures (base, pants, shirt)\n"
1587 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1588 "#ifdef USEALPHAKILL\n"
1589 "       if (color.a < 0.5)\n"
1590 "               discard;\n"
1591 "#endif\n"
1592 "       color.a *= Alpha;\n"
1593 "#ifdef USECOLORMAPPING\n"
1594 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1595 "#endif\n"
1596 "#ifdef USEVERTEXTEXTUREBLEND\n"
1597 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1598 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1599 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1600 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1601 "       color.a = 1.0;\n"
1602 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1603 "#endif\n"
1604 "\n"
1605 "       // get the surface normal\n"
1606 "#ifdef USEVERTEXTEXTUREBLEND\n"
1607 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1608 "#else\n"
1609 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#endif\n"
1611 "\n"
1612 "       // get the material colors\n"
1613 "       myhalf3 diffusetex = color.rgb;\n"
1614 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1615 "# ifdef USEVERTEXTEXTUREBLEND\n"
1616 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1617 "# else\n"
1618 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1619 "# endif\n"
1620 "#endif\n"
1621 "\n"
1622 "#ifdef USEREFLECTCUBE\n"
1623 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1624 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1625 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1626 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1627 "#endif\n"
1628 "\n"
1629 "\n"
1630 "\n"
1631 "\n"
1632 "#ifdef MODE_LIGHTSOURCE\n"
1633 "       // light source\n"
1634 "#ifdef USEDIFFUSE\n"
1635 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1636 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1637 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1638 "#ifdef USESPECULAR\n"
1639 "#ifdef USEEXACTSPECULARMATH\n"
1640 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1641 "#else\n"
1642 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1643 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1644 "#endif\n"
1645 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1646 "#endif\n"
1647 "#else\n"
1648 "       color.rgb = diffusetex * Color_Ambient;\n"
1649 "#endif\n"
1650 "       color.rgb *= LightColor;\n"
1651 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1652 "#if defined(USESHADOWMAP2D)\n"
1653 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1654 "#endif\n"
1655 "# ifdef USECUBEFILTER\n"
1656 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1657 "# endif\n"
1658 "#endif // MODE_LIGHTSOURCE\n"
1659 "\n"
1660 "\n"
1661 "\n"
1662 "\n"
1663 "#ifdef MODE_LIGHTDIRECTION\n"
1664 "#define SHADING\n"
1665 "#ifdef USEDIFFUSE\n"
1666 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1667 "#endif\n"
1668 "#define lightcolor LightColor\n"
1669 "#endif // MODE_LIGHTDIRECTION\n"
1670 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1671 "#define SHADING\n"
1672 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1673 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1674 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1675 "       // convert modelspace light vector to tangentspace\n"
1676 "       myhalf3 lightnormal;\n"
1677 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1678 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1679 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1680 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1681 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1682 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1683 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1684 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1685 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1686 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1687 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1688 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1689 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1690 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1691 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1692 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1693 "#define SHADING\n"
1694 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1695 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1696 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1697 "#endif\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_FAKELIGHT\n"
1703 "#define SHADING\n"
1704 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1705 "myhalf3 lightcolor = myhalf3(1.0);\n"
1706 "#endif // MODE_FAKELIGHT\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "#ifdef MODE_LIGHTMAP\n"
1712 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1713 "#endif // MODE_LIGHTMAP\n"
1714 "#ifdef MODE_VERTEXCOLOR\n"
1715 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1716 "#endif // MODE_VERTEXCOLOR\n"
1717 "#ifdef MODE_FLATCOLOR\n"
1718 "       color.rgb = diffusetex * Color_Ambient;\n"
1719 "#endif // MODE_FLATCOLOR\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef SHADING\n"
1725 "# ifdef USEDIFFUSE\n"
1726 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1727 "#  ifdef USESPECULAR\n"
1728 "#   ifdef USEEXACTSPECULARMATH\n"
1729 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1730 "#   else\n"
1731 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1732 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1733 "#   endif\n"
1734 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1735 "#  else\n"
1736 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1737 "#  endif\n"
1738 "# else\n"
1739 "       color.rgb = diffusetex * Color_Ambient;\n"
1740 "# endif\n"
1741 "#endif\n"
1742 "\n"
1743 "#ifdef USESHADOWMAPORTHO\n"
1744 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef USEDEFERREDLIGHTMAP\n"
1748 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1749 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1750 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1751 "#endif\n"
1752 "\n"
1753 "#ifdef USEGLOW\n"
1754 "#ifdef USEVERTEXTEXTUREBLEND\n"
1755 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1756 "#else\n"
1757 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1758 "#endif\n"
1759 "#endif\n"
1760 "\n"
1761 "#ifdef USEFOG\n"
1762 "       color.rgb = FogVertex(color.rgb);\n"
1763 "#endif\n"
1764 "\n"
1765 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1766 "#ifdef USEREFLECTION\n"
1767 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1768 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1769 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1770 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1771 "       // FIXME temporary hack to detect the case that the reflection\n"
1772 "       // gets blackened at edges due to leaving the area that contains actual\n"
1773 "       // content.\n"
1774 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1775 "       // 'appening.\n"
1776 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1777 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1778 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1780 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1781 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1782 "#endif\n"
1783 "\n"
1784 "       gl_FragColor = vec4(color);\n"
1785 "}\n"
1786 "#endif // FRAGMENT_SHADER\n"
1787 "\n"
1788 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1789 "#endif // !MODE_DEFERREDGEOMETRY\n"
1790 "#endif // !MODE_WATER\n"
1791 "#endif // !MODE_REFRACTION\n"
1792 "#endif // !MODE_BLOOMBLUR\n"
1793 "#endif // !MODE_GENERIC\n"
1794 "#endif // !MODE_POSTPROCESS\n"
1795 "#endif // !MODE_SHOWDEPTH\n"
1796 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1797 ;
1798
1799 /*
1800 =========================================================================================================================================================
1801
1802
1803
1804 =========================================================================================================================================================
1805
1806
1807
1808 =========================================================================================================================================================
1809
1810
1811
1812 =========================================================================================================================================================
1813
1814
1815
1816 =========================================================================================================================================================
1817
1818
1819
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825 */
1826
1827 const char *builtincgshaderstring =
1828 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1829 "// written by Forest 'LordHavoc' Hale\n"
1830 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1831 "\n"
1832 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1833 "#if defined(USEREFLECTION)\n"
1834 "#undef USESHADOWMAPORTHO\n"
1835 "#endif\n"
1836 "\n"
1837 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1838 "# define USEFOG\n"
1839 "#endif\n"
1840 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1841 "#define USELIGHTMAP\n"
1842 "#endif\n"
1843 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1844 "#define USEEYEVECTOR\n"
1845 "#endif\n"
1846 "\n"
1847 "#ifdef FRAGMENT_SHADER\n"
1848 "#ifdef HLSL\n"
1849 "//#undef USESHADOWMAPPCF\n"
1850 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1851 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1852 "#else\n"
1853 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1854 "#endif\n"
1855 "#endif\n"
1856 "\n"
1857 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1858 "#ifdef VERTEX_SHADER\n"
1859 "void main\n"
1860 "(\n"
1861 "float4 gl_Vertex : POSITION,\n"
1862 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1863 "out float4 gl_Position : POSITION,\n"
1864 "out float Depth : TEXCOORD0\n"
1865 ")\n"
1866 "{\n"
1867 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1868 "       Depth = gl_Position.z;\n"
1869 "}\n"
1870 "#endif\n"
1871 "\n"
1872 "#ifdef FRAGMENT_SHADER\n"
1873 "void main\n"
1874 "(\n"
1875 "float Depth : TEXCOORD0,\n"
1876 "out float4 gl_FragColor : COLOR\n"
1877 ")\n"
1878 "{\n"
1879 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1880 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1881 "       temp.yz -= floor(temp.yz);\n"
1882 "       gl_FragColor = temp;\n"
1883 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1884 "}\n"
1885 "#endif\n"
1886 "#else // !MODE_DEPTH_ORSHADOW\n"
1887 "\n"
1888 "\n"
1889 "\n"
1890 "\n"
1891 "#ifdef MODE_SHOWDEPTH\n"
1892 "#ifdef VERTEX_SHADER\n"
1893 "void main\n"
1894 "(\n"
1895 "float4 gl_Vertex : POSITION,\n"
1896 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1897 "out float4 gl_Position : POSITION,\n"
1898 "out float4 gl_FrontColor : COLOR0\n"
1899 ")\n"
1900 "{\n"
1901 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1902 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1903 "}\n"
1904 "#endif\n"
1905 "\n"
1906 "#ifdef FRAGMENT_SHADER\n"
1907 "void main\n"
1908 "(\n"
1909 "float4 gl_FrontColor : COLOR0,\n"
1910 "out float4 gl_FragColor : COLOR\n"
1911 ")\n"
1912 "{\n"
1913 "       gl_FragColor = gl_FrontColor;\n"
1914 "}\n"
1915 "#endif\n"
1916 "#else // !MODE_SHOWDEPTH\n"
1917 "\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "#ifdef MODE_POSTPROCESS\n"
1922 "\n"
1923 "#ifdef VERTEX_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float4 gl_Vertex : POSITION,\n"
1927 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1928 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1929 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1930 "out float4 gl_Position : POSITION,\n"
1931 "out float2 TexCoord1 : TEXCOORD0,\n"
1932 "out float2 TexCoord2 : TEXCOORD1\n"
1933 ")\n"
1934 "{\n"
1935 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1936 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1937 "#ifdef USEBLOOM\n"
1938 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1939 "#endif\n"
1940 "}\n"
1941 "#endif\n"
1942 "\n"
1943 "#ifdef FRAGMENT_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float2 TexCoord1 : TEXCOORD0,\n"
1947 "float2 TexCoord2 : TEXCOORD1,\n"
1948 "uniform sampler Texture_First : register(s0),\n"
1949 "#ifdef USEBLOOM\n"
1950 "uniform sampler Texture_Second : register(s1),\n"
1951 "#endif\n"
1952 "#ifdef USEGAMMARAMPS\n"
1953 "uniform sampler Texture_GammaRamps : register(s2),\n"
1954 "#endif\n"
1955 "#ifdef USESATURATION\n"
1956 "uniform float Saturation : register(c30),\n"
1957 "#endif\n"
1958 "#ifdef USEVIEWTINT\n"
1959 "uniform float4 ViewTintColor : register(c41),\n"
1960 "#endif\n"
1961 "uniform float4 UserVec1 : register(c37),\n"
1962 "uniform float4 UserVec2 : register(c38),\n"
1963 "uniform float4 UserVec3 : register(c39),\n"
1964 "uniform float4 UserVec4 : register(c40),\n"
1965 "uniform float ClientTime : register(c2),\n"
1966 "uniform float2 PixelSize : register(c25),\n"
1967 "uniform float4 BloomColorSubtract : register(c43),\n"
1968 "out float4 gl_FragColor : COLOR\n"
1969 ")\n"
1970 "{\n"
1971 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1972 "#ifdef USEBLOOM\n"
1973 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1974 "#endif\n"
1975 "#ifdef USEVIEWTINT\n"
1976 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1977 "#endif\n"
1978 "\n"
1979 "#ifdef USEPOSTPROCESSING\n"
1980 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1981 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1982 "       float sobel = 1.0;\n"
1983 "       // float2 ts = textureSize(Texture_First, 0);\n"
1984 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1985 "       float2 px = PixelSize;\n"
1986 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1987 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1988 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1989 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1990 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1991 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1992 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1993 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1994 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1995 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1996 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1997 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1998 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1999 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2000 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2001 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2002 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2003 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2004 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2005 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2006 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2007 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2008 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2009 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2010 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2011 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2012 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2016 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2017 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2018 "#endif\n"
2019 "\n"
2020 "#ifdef USESATURATION\n"
2021 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2022 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2023 "       // 'vampire sight' effect, wheres red is compensated\n"
2024 "       #ifdef SATURATION_REDCOMPENSATE\n"
2025 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2026 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2027 "               gl_FragColor.r += r;\n"
2028 "       #else\n"
2029 "               // normal desaturation\n"
2030 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2031 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2032 "       #endif\n"
2033 "#endif\n"
2034 "\n"
2035 "#ifdef USEGAMMARAMPS\n"
2036 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2037 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2038 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2039 "#endif\n"
2040 "}\n"
2041 "#endif\n"
2042 "#else // !MODE_POSTPROCESS\n"
2043 "\n"
2044 "\n"
2045 "\n"
2046 "\n"
2047 "#ifdef MODE_GENERIC\n"
2048 "#ifdef VERTEX_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float4 gl_Vertex : POSITION,\n"
2052 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2053 "float4 gl_Color : COLOR0,\n"
2054 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2055 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2056 "out float4 gl_Position : POSITION,\n"
2057 "#ifdef USEDIFFUSE\n"
2058 "out float2 TexCoord1 : TEXCOORD0,\n"
2059 "#endif\n"
2060 "#ifdef USESPECULAR\n"
2061 "out float2 TexCoord2 : TEXCOORD1,\n"
2062 "#endif\n"
2063 "out float4 gl_FrontColor : COLOR\n"
2064 ")\n"
2065 "{\n"
2066 "#ifdef HLSL\n"
2067 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2068 "#else\n"
2069 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2070 "#endif\n"
2071 "#ifdef USEDIFFUSE\n"
2072 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2073 "#endif\n"
2074 "#ifdef USESPECULAR\n"
2075 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2076 "#endif\n"
2077 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2078 "}\n"
2079 "#endif\n"
2080 "\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2082 "\n"
2083 "void main\n"
2084 "(\n"
2085 "float4 gl_FrontColor : COLOR0,\n"
2086 "float2 TexCoord1 : TEXCOORD0,\n"
2087 "float2 TexCoord2 : TEXCOORD1,\n"
2088 "#ifdef USEDIFFUSE\n"
2089 "uniform sampler Texture_First : register(s0),\n"
2090 "#endif\n"
2091 "#ifdef USESPECULAR\n"
2092 "uniform sampler Texture_Second : register(s1),\n"
2093 "#endif\n"
2094 "out float4 gl_FragColor : COLOR\n"
2095 ")\n"
2096 "{\n"
2097 "#ifdef USEVIEWTINT\n"
2098 "       gl_FragColor = gl_FrontColor;\n"
2099 "#else\n"
2100 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2101 "#endif\n"
2102 "#ifdef USEDIFFUSE\n"
2103 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2104 "#endif\n"
2105 "\n"
2106 "#ifdef USESPECULAR\n"
2107 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2108 "# ifdef USECOLORMAPPING\n"
2109 "       gl_FragColor *= tex2;\n"
2110 "# endif\n"
2111 "# ifdef USEGLOW\n"
2112 "       gl_FragColor += tex2;\n"
2113 "# endif\n"
2114 "# ifdef USEVERTEXTEXTUREBLEND\n"
2115 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2116 "# endif\n"
2117 "#endif\n"
2118 "}\n"
2119 "#endif\n"
2120 "#else // !MODE_GENERIC\n"
2121 "\n"
2122 "\n"
2123 "\n"
2124 "\n"
2125 "#ifdef MODE_BLOOMBLUR\n"
2126 "#ifdef VERTEX_SHADER\n"
2127 "void main\n"
2128 "(\n"
2129 "float4 gl_Vertex : POSITION,\n"
2130 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2131 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2132 "out float4 gl_Position : POSITION,\n"
2133 "out float2 TexCoord : TEXCOORD0\n"
2134 ")\n"
2135 "{\n"
2136 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2137 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2138 "}\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef FRAGMENT_SHADER\n"
2142 "\n"
2143 "void main\n"
2144 "(\n"
2145 "float2 TexCoord : TEXCOORD0,\n"
2146 "uniform sampler Texture_First : register(s0),\n"
2147 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2148 "out float4 gl_FragColor : COLOR\n"
2149 ")\n"
2150 "{\n"
2151 "       int i;\n"
2152 "       float2 tc = TexCoord;\n"
2153 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2154 "       tc += BloomBlur_Parameters.xy;\n"
2155 "       for (i = 1;i < SAMPLES;i++)\n"
2156 "       {\n"
2157 "               color += tex2D(Texture_First, tc).rgb;\n"
2158 "               tc += BloomBlur_Parameters.xy;\n"
2159 "       }\n"
2160 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2161 "}\n"
2162 "#endif\n"
2163 "#else // !MODE_BLOOMBLUR\n"
2164 "#ifdef MODE_REFRACTION\n"
2165 "#ifdef VERTEX_SHADER\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "uniform float4x4 TexMatrix : register(c0),\n"
2172 "uniform float3 EyePosition : register(c24),\n"
2173 "out float4 gl_Position : POSITION,\n"
2174 "out float2 TexCoord : TEXCOORD0,\n"
2175 "out float3 EyeVector : TEXCOORD1,\n"
2176 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2177 ")\n"
2178 "{\n"
2179 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2180 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2181 "       ModelViewProjectionPosition = gl_Position;\n"
2182 "}\n"
2183 "#endif\n"
2184 "\n"
2185 "#ifdef FRAGMENT_SHADER\n"
2186 "void main\n"
2187 "(\n"
2188 "float2 TexCoord : TEXCOORD0,\n"
2189 "float3 EyeVector : TEXCOORD1,\n"
2190 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2191 "uniform sampler Texture_Normal : register(s0),\n"
2192 "uniform sampler Texture_Refraction : register(s3),\n"
2193 "uniform sampler Texture_Reflection : register(s7),\n"
2194 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2195 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2196 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2197 "uniform float4 RefractColor : register(c29),\n"
2198 "out float4 gl_FragColor : COLOR\n"
2199 ")\n"
2200 "{\n"
2201 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2202 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2203 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2204 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2205 "       // FIXME temporary hack to detect the case that the reflection\n"
2206 "       // gets blackened at edges due to leaving the area that contains actual\n"
2207 "       // content.\n"
2208 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2209 "       // 'appening.\n"
2210 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2211 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2212 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2214 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2215 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2216 "}\n"
2217 "#endif\n"
2218 "#else // !MODE_REFRACTION\n"
2219 "\n"
2220 "\n"
2221 "\n"
2222 "\n"
2223 "#ifdef MODE_WATER\n"
2224 "#ifdef VERTEX_SHADER\n"
2225 "\n"
2226 "void main\n"
2227 "(\n"
2228 "float4 gl_Vertex : POSITION,\n"
2229 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2230 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2231 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2232 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2233 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2234 "uniform float4x4 TexMatrix : register(c0),\n"
2235 "uniform float3 EyePosition : register(c24),\n"
2236 "out float4 gl_Position : POSITION,\n"
2237 "out float2 TexCoord : TEXCOORD0,\n"
2238 "out float3 EyeVector : TEXCOORD1,\n"
2239 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2240 ")\n"
2241 "{\n"
2242 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2243 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2244 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2245 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2246 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2247 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2248 "       ModelViewProjectionPosition = gl_Position;\n"
2249 "}\n"
2250 "#endif\n"
2251 "\n"
2252 "#ifdef FRAGMENT_SHADER\n"
2253 "void main\n"
2254 "(\n"
2255 "float2 TexCoord : TEXCOORD0,\n"
2256 "float3 EyeVector : TEXCOORD1,\n"
2257 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2258 "uniform sampler Texture_Normal : register(s0),\n"
2259 "uniform sampler Texture_Refraction : register(s3),\n"
2260 "uniform sampler Texture_Reflection : register(s7),\n"
2261 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2262 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2263 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2264 "uniform float4 RefractColor : register(c29),\n"
2265 "uniform float4 ReflectColor : register(c26),\n"
2266 "uniform float ReflectFactor : register(c27),\n"
2267 "uniform float ReflectOffset : register(c28),\n"
2268 "out float4 gl_FragColor : COLOR\n"
2269 ")\n"
2270 "{\n"
2271 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2272 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2273 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2274 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2275 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2276 "       // FIXME temporary hack to detect the case that the reflection\n"
2277 "       // gets blackened at edges due to leaving the area that contains actual\n"
2278 "       // content.\n"
2279 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2280 "       // 'appening.\n"
2281 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2282 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2283 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2285 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2286 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2287 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2288 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2289 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2290 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2291 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2292 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2293 "}\n"
2294 "#endif\n"
2295 "#else // !MODE_WATER\n"
2296 "\n"
2297 "\n"
2298 "\n"
2299 "\n"
2300 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2301 "\n"
2302 "// fragment shader specific:\n"
2303 "#ifdef FRAGMENT_SHADER\n"
2304 "\n"
2305 "#ifdef USEFOG\n"
2306 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2307 "{\n"
2308 "       float fogfrac;\n"
2309 "#ifdef USEFOGHEIGHTTEXTURE\n"
2310 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2311 "       fogfrac = fogheightpixel.a;\n"
2312 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2313 "#else\n"
2314 "# ifdef USEFOGOUTSIDE\n"
2315 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2316 "# else\n"
2317 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2318 "# endif\n"
2319 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2320 "#endif\n"
2321 "}\n"
2322 "#endif\n"
2323 "\n"
2324 "#ifdef USEOFFSETMAPPING\n"
2325 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2326 "{\n"
2327 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2328 "       // 14 sample relief mapping: linear search and then binary search\n"
2329 "       // this basically steps forward a small amount repeatedly until it finds\n"
2330 "       // itself inside solid, then jitters forward and back using decreasing\n"
2331 "       // amounts to find the impact\n"
2332 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2333 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2334 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2335 "       float3 RT = float3(TexCoord, 1);\n"
2336 "       OffsetVector *= 0.1;\n"
2337 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2338 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2347 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2351 "       return RT.xy;\n"
2352 "#else\n"
2353 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2354 "       // this basically moves forward the full distance, and then backs up based\n"
2355 "       // on height of samples\n"
2356 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2357 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2358 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2359 "       TexCoord += OffsetVector;\n"
2360 "       OffsetVector *= 0.333;\n"
2361 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2362 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       return TexCoord;\n"
2365 "#endif\n"
2366 "}\n"
2367 "#endif // USEOFFSETMAPPING\n"
2368 "\n"
2369 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2370 "#if defined(USESHADOWMAP2D)\n"
2371 "# ifdef USESHADOWMAPORTHO\n"
2372 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2373 "# else\n"
2374 "#  ifdef USESHADOWMAPVSDCT\n"
2375 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2376 "{\n"
2377 "       float3 adir = abs(dir);\n"
2378 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2379 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2380 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2381 "}\n"
2382 "#  else\n"
2383 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2384 "{\n"
2385 "       float3 adir = abs(dir);\n"
2386 "       float ma = adir.z;\n"
2387 "       float4 proj = float4(dir, 2.5);\n"
2388 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2389 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2390 "#ifdef HLSL\n"
2391 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2392 "#else\n"
2393 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2394 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2395 "#endif\n"
2396 "}\n"
2397 "#  endif\n"
2398 "# endif\n"
2399 "#endif // defined(USESHADOWMAP2D)\n"
2400 "\n"
2401 "# ifdef USESHADOWMAP2D\n"
2402 "#ifdef USESHADOWMAPVSDCT\n"
2403 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2404 "#else\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2406 "#endif\n"
2407 "{\n"
2408 "#ifdef USESHADOWMAPVSDCT\n"
2409 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2410 "#else\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2412 "#endif\n"
2413 "       float f;\n"
2414 "\n"
2415 "#  ifdef USESHADOWSAMPLER\n"
2416 "#    ifdef USESHADOWMAPPCF\n"
2417 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2418 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2419 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2420 "#    else\n"
2421 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2422 "#    endif\n"
2423 "#  else\n"
2424 "#    ifdef USESHADOWMAPPCF\n"
2425 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2426 "#      ifdef GL_ARB_texture_gather\n"
2427 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2428 "#      else\n"
2429 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2430 "#      endif\n"
2431 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2432 "#      if USESHADOWMAPPCF > 1\n"
2433 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2434 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2435 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2436 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2437 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2438 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2439 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2440 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2441 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2442 "       float4 locols = float4(group1.ab, group3.ab);\n"
2443 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2444 "       locols.yz += group2.ab;\n"
2445 "       hicols.yz += group8.rg;\n"
2446 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2447 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2448 "                               lerp(locols, hicols, offset.y);\n"
2449 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2450 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2451 "       f = dot(cols, float4(1.0/25.0));\n"
2452 "#      else\n"
2453 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2454 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2455 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2456 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2457 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2458 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2459 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2460 "#      endif\n"
2461 "#     else\n"
2462 "#      ifdef GL_EXT_gpu_shader4\n"
2463 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2464 "#      else\n"
2465 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2466 "#      endif\n"
2467 "#      if USESHADOWMAPPCF > 1\n"
2468 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2469 "       center *= ShadowMap_TextureScale;\n"
2470 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2471 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2472 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2473 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2474 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2475 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2476 "#      else\n"
2477 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2478 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2479 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2480 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2481 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2482 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2483 "#      endif\n"
2484 "#     endif\n"
2485 "#    else\n"
2486 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2487 "#    endif\n"
2488 "#  endif\n"
2489 "#  ifdef USESHADOWMAPORTHO\n"
2490 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2491 "#  else\n"
2492 "       return f;\n"
2493 "#  endif\n"
2494 "}\n"
2495 "# endif\n"
2496 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2497 "#endif // FRAGMENT_SHADER\n"
2498 "\n"
2499 "\n"
2500 "\n"
2501 "\n"
2502 "#ifdef MODE_DEFERREDGEOMETRY\n"
2503 "#ifdef VERTEX_SHADER\n"
2504 "void main\n"
2505 "(\n"
2506 "float4 gl_Vertex : POSITION,\n"
2507 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2508 "#ifdef USEVERTEXTEXTUREBLEND\n"
2509 "float4 gl_Color : COLOR0,\n"
2510 "#endif\n"
2511 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2512 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2513 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2514 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2515 "uniform float4x4 TexMatrix : register(c0),\n"
2516 "#ifdef USEVERTEXTEXTUREBLEND\n"
2517 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2518 "#endif\n"
2519 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2520 "#ifdef USEOFFSETMAPPING\n"
2521 "uniform float3 EyePosition : register(c24),\n"
2522 "#endif\n"
2523 "out float4 gl_Position : POSITION,\n"
2524 "#ifdef USEVERTEXTEXTUREBLEND\n"
2525 "out float4 gl_FrontColor : COLOR,\n"
2526 "#endif\n"
2527 "out float4 TexCoordBoth : TEXCOORD0,\n"
2528 "#ifdef USEOFFSETMAPPING\n"
2529 "out float3 EyeVector : TEXCOORD2,\n"
2530 "#endif\n"
2531 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2532 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2533 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2534 ")\n"
2535 "{\n"
2536 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2537 "#ifdef USEVERTEXTEXTUREBLEND\n"
2538 "#ifdef HLSL\n"
2539 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2540 "#else\n"
2541 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2542 "#endif\n"
2543 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2544 "#endif\n"
2545 "\n"
2546 "       // transform unnormalized eye direction into tangent space\n"
2547 "#ifdef USEOFFSETMAPPING\n"
2548 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2549 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2550 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2551 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2552 "#endif\n"
2553 "\n"
2554 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2555 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2556 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2557 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2558 "       VectorR.w = gl_Position.z;\n"
2559 "}\n"
2560 "#endif // VERTEX_SHADER\n"
2561 "\n"
2562 "#ifdef FRAGMENT_SHADER\n"
2563 "void main\n"
2564 "(\n"
2565 "float4 TexCoordBoth : TEXCOORD0,\n"
2566 "float3 EyeVector : TEXCOORD2,\n"
2567 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2568 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2569 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2570 "uniform sampler Texture_Normal : register(s0),\n"
2571 "#ifdef USEALPHAKILL\n"
2572 "uniform sampler Texture_Color : register(s1),\n"
2573 "#endif\n"
2574 "uniform sampler Texture_Gloss : register(s2),\n"
2575 "#ifdef USEVERTEXTEXTUREBLEND\n"
2576 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2577 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2578 "#endif\n"
2579 "#ifdef USEOFFSETMAPPING\n"
2580 "uniform float OffsetMapping_Scale : register(c24),\n"
2581 "#endif\n"
2582 "uniform half SpecularPower : register(c36),\n"
2583 "#ifdef HLSL\n"
2584 "out float4 gl_FragData0 : COLOR0,\n"
2585 "out float4 gl_FragData1 : COLOR1\n"
2586 "#else\n"
2587 "out float4 gl_FragColor : COLOR\n"
2588 "#endif\n"
2589 ")\n"
2590 "{\n"
2591 "       float2 TexCoord = TexCoordBoth.xy;\n"
2592 "#ifdef USEOFFSETMAPPING\n"
2593 "       // apply offsetmapping\n"
2594 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2595 "#define TexCoord TexCoordOffset\n"
2596 "#endif\n"
2597 "\n"
2598 "#ifdef USEALPHAKILL\n"
2599 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2600 "               discard;\n"
2601 "#endif\n"
2602 "\n"
2603 "#ifdef USEVERTEXTEXTUREBLEND\n"
2604 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2605 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2606 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2607 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2608 "#endif\n"
2609 "\n"
2610 "#ifdef USEVERTEXTEXTUREBLEND\n"
2611 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2612 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2613 "#else\n"
2614 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2615 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2616 "#endif\n"
2617 "\n"
2618 "#ifdef HLSL\n"
2619 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2620 "       float Depth = VectorR.w / 256.0;\n"
2621 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2622 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2623 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2624 "       gl_FragData1 = depthcolor;\n"
2625 "#else\n"
2626 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2627 "#endif\n"
2628 "}\n"
2629 "#endif // FRAGMENT_SHADER\n"
2630 "#else // !MODE_DEFERREDGEOMETRY\n"
2631 "\n"
2632 "\n"
2633 "\n"
2634 "\n"
2635 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2636 "#ifdef VERTEX_SHADER\n"
2637 "void main\n"
2638 "(\n"
2639 "float4 gl_Vertex : POSITION,\n"
2640 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2641 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2642 "out float4 gl_Position : POSITION,\n"
2643 "out float4 ModelViewPosition : TEXCOORD0\n"
2644 ")\n"
2645 "{\n"
2646 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2647 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2648 "}\n"
2649 "#endif // VERTEX_SHADER\n"
2650 "\n"
2651 "#ifdef FRAGMENT_SHADER\n"
2652 "void main\n"
2653 "(\n"
2654 "#ifdef HLSL\n"
2655 "float2 Pixel : VPOS,\n"
2656 "#else\n"
2657 "float2 Pixel : WPOS,\n"
2658 "#endif\n"
2659 "float4 ModelViewPosition : TEXCOORD0,\n"
2660 "uniform float4x4 ViewToLight : register(c44),\n"
2661 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2662 "uniform float3 LightPosition : register(c23),\n"
2663 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2664 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2665 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2666 "#ifdef USESPECULAR\n"
2667 "uniform half3 DeferredColor_Specular : register(c11),\n"
2668 "uniform half SpecularPower : register(c36),\n"
2669 "#endif\n"
2670 "uniform sampler Texture_Attenuation : register(s9),\n"
2671 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2672 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2673 "\n"
2674 "#ifdef USECUBEFILTER\n"
2675 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2676 "#endif\n"
2677 "\n"
2678 "#ifdef USESHADOWMAP2D\n"
2679 "# ifdef USESHADOWSAMPLER\n"
2680 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2681 "# else\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# endif\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef USESHADOWMAPVSDCT\n"
2687 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(USESHADOWMAP2D)\n"
2691 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2692 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2693 "#endif\n"
2694 "\n"
2695 "out float4 gl_FragData0 : COLOR0,\n"
2696 "out float4 gl_FragData1 : COLOR1\n"
2697 ")\n"
2698 "{\n"
2699 "       // calculate viewspace pixel position\n"
2700 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2701 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2702 "       float3 position;\n"
2703 "#ifdef HLSL\n"
2704 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2705 "#else\n"
2706 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2707 "#endif\n"
2708 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2709 "       // decode viewspace pixel normal\n"
2710 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2711 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2712 "       // surfacenormal = pixel normal in viewspace\n"
2713 "       // LightVector = pixel to light in viewspace\n"
2714 "       // CubeVector = position in lightspace\n"
2715 "       // eyevector = pixel to view in viewspace\n"
2716 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2717 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2718 "#ifdef USEDIFFUSE\n"
2719 "       // calculate diffuse shading\n"
2720 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2721 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2722 "#endif\n"
2723 "#ifdef USESPECULAR\n"
2724 "       // calculate directional shading\n"
2725 "       float3 eyevector = position * -1.0;\n"
2726 "#  ifdef USEEXACTSPECULARMATH\n"
2727 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2728 "#  else\n"
2729 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2730 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2731 "#  endif\n"
2732 "#endif\n"
2733 "\n"
2734 "#if defined(USESHADOWMAP2D)\n"
2735 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2736 "#ifdef USESHADOWMAPVSDCT\n"
2737 ", Texture_CubeProjection\n"
2738 "#endif\n"
2739 "       ));\n"
2740 "#endif\n"
2741 "\n"
2742 "#ifdef USEDIFFUSE\n"
2743 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2744 "#else\n"
2745 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2746 "#endif\n"
2747 "#ifdef USESPECULAR\n"
2748 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2749 "#else\n"
2750 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2751 "#endif\n"
2752 "\n"
2753 "# ifdef USECUBEFILTER\n"
2754 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2755 "       gl_FragData0.rgb *= cubecolor;\n"
2756 "       gl_FragData1.rgb *= cubecolor;\n"
2757 "# endif\n"
2758 "}\n"
2759 "#endif // FRAGMENT_SHADER\n"
2760 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2761 "\n"
2762 "\n"
2763 "\n"
2764 "\n"
2765 "#ifdef VERTEX_SHADER\n"
2766 "void main\n"
2767 "(\n"
2768 "float4 gl_Vertex : POSITION,\n"
2769 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2770 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2771 "float4 gl_Color : COLOR0,\n"
2772 "#endif\n"
2773 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2774 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2775 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2776 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2777 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2778 "\n"
2779 "uniform float3 EyePosition : register(c24),\n"
2780 "uniform float4x4 TexMatrix : register(c0),\n"
2781 "#ifdef USEVERTEXTEXTUREBLEND\n"
2782 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2783 "#endif\n"
2784 "#ifdef MODE_LIGHTSOURCE\n"
2785 "uniform float4x4 ModelToLight : register(c20),\n"
2786 "#endif\n"
2787 "#ifdef MODE_LIGHTSOURCE\n"
2788 "uniform float3 LightPosition : register(c27),\n"
2789 "#endif\n"
2790 "#ifdef MODE_LIGHTDIRECTION\n"
2791 "uniform float3 LightDir : register(c26),\n"
2792 "#endif\n"
2793 "uniform float4 FogPlane : register(c25),\n"
2794 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2795 "uniform float3 LightPosition : register(c27),\n"
2796 "#endif\n"
2797 "#ifdef USESHADOWMAPORTHO\n"
2798 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2799 "#endif\n"
2800 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2801 "out float4 gl_FrontColor : COLOR,\n"
2802 "#endif\n"
2803 "out float4 TexCoordBoth : TEXCOORD0,\n"
2804 "#ifdef USELIGHTMAP\n"
2805 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2806 "#endif\n"
2807 "#ifdef USEEYEVECTOR\n"
2808 "out float3 EyeVector : TEXCOORD2,\n"
2809 "#endif\n"
2810 "#ifdef USEREFLECTION\n"
2811 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2812 "#endif\n"
2813 "#ifdef USEFOG\n"
2814 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2815 "#endif\n"
2816 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2817 "out float3 LightVector : TEXCOORD1,\n"
2818 "#endif\n"
2819 "#ifdef MODE_LIGHTSOURCE\n"
2820 "out float3 CubeVector : TEXCOORD3,\n"
2821 "#endif\n"
2822 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2823 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2824 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2825 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2826 "#endif\n"
2827 "#ifdef USESHADOWMAPORTHO\n"
2828 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2829 "#endif\n"
2830 "out float4 gl_Position : POSITION\n"
2831 ")\n"
2832 "{\n"
2833 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2834 "#ifdef HLSL\n"
2835 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2836 "#else\n"
2837 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2838 "#endif\n"
2839 "#endif\n"
2840 "       // copy the surface texcoord\n"
2841 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2842 "#ifdef USEVERTEXTEXTUREBLEND\n"
2843 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2844 "#endif\n"
2845 "#ifdef USELIGHTMAP\n"
2846 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2847 "#endif\n"
2848 "\n"
2849 "#ifdef MODE_LIGHTSOURCE\n"
2850 "       // transform vertex position into light attenuation/cubemap space\n"
2851 "       // (-1 to +1 across the light box)\n"
2852 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2853 "\n"
2854 "# ifdef USEDIFFUSE\n"
2855 "       // transform unnormalized light direction into tangent space\n"
2856 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2857 "       //  normalize it per pixel)\n"
2858 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2859 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2860 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2861 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2862 "# endif\n"
2863 "#endif\n"
2864 "\n"
2865 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2866 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2867 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2868 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2869 "#endif\n"
2870 "\n"
2871 "       // transform unnormalized eye direction into tangent space\n"
2872 "#ifdef USEEYEVECTOR\n"
2873 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2874 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2875 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2876 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USEFOG\n"
2880 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2882 "#endif\n"
2883 "\n"
2884 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2885 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2886 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2887 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2888 "#endif\n"
2889 "\n"
2890 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2892 "\n"
2893 "#ifdef USESHADOWMAPORTHO\n"
2894 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2895 "#endif\n"
2896 "\n"
2897 "#ifdef USEREFLECTION\n"
2898 "       ModelViewProjectionPosition = gl_Position;\n"
2899 "#endif\n"
2900 "}\n"
2901 "#endif // VERTEX_SHADER\n"
2902 "\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "#ifdef FRAGMENT_SHADER\n"
2907 "void main\n"
2908 "(\n"
2909 "#ifdef USEDEFERREDLIGHTMAP\n"
2910 "#ifdef HLSL\n"
2911 "float2 Pixel : VPOS,\n"
2912 "#else\n"
2913 "float2 Pixel : WPOS,\n"
2914 "#endif\n"
2915 "#endif\n"
2916 "float4 gl_FrontColor : COLOR,\n"
2917 "float4 TexCoordBoth : TEXCOORD0,\n"
2918 "#ifdef USELIGHTMAP\n"
2919 "float2 TexCoordLightmap : TEXCOORD1,\n"
2920 "#endif\n"
2921 "#ifdef USEEYEVECTOR\n"
2922 "float3 EyeVector : TEXCOORD2,\n"
2923 "#endif\n"
2924 "#ifdef USEREFLECTION\n"
2925 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2926 "#endif\n"
2927 "#ifdef USEFOG\n"
2928 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2929 "#endif\n"
2930 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2931 "float3 LightVector : TEXCOORD1,\n"
2932 "#endif\n"
2933 "#ifdef MODE_LIGHTSOURCE\n"
2934 "float3 CubeVector : TEXCOORD3,\n"
2935 "#endif\n"
2936 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2937 "float4 ModelViewPosition : TEXCOORD0,\n"
2938 "#endif\n"
2939 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2940 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2941 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2942 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2943 "#endif\n"
2944 "#ifdef USESHADOWMAPORTHO\n"
2945 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2946 "#endif\n"
2947 "\n"
2948 "uniform sampler Texture_Normal : register(s0),\n"
2949 "uniform sampler Texture_Color : register(s1),\n"
2950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2951 "uniform sampler Texture_Gloss : register(s2),\n"
2952 "#endif\n"
2953 "#ifdef USEGLOW\n"
2954 "uniform sampler Texture_Glow : register(s3),\n"
2955 "#endif\n"
2956 "#ifdef USEVERTEXTEXTUREBLEND\n"
2957 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2958 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2959 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2960 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2961 "#endif\n"
2962 "#ifdef USEGLOW\n"
2963 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2964 "#endif\n"
2965 "#endif\n"
2966 "#ifdef USECOLORMAPPING\n"
2967 "uniform sampler Texture_Pants : register(s4),\n"
2968 "uniform sampler Texture_Shirt : register(s7),\n"
2969 "#endif\n"
2970 "#ifdef USEFOG\n"
2971 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2972 "uniform sampler Texture_FogMask : register(s8),\n"
2973 "#endif\n"
2974 "#ifdef USELIGHTMAP\n"
2975 "uniform sampler Texture_Lightmap : register(s9),\n"
2976 "#endif\n"
2977 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2978 "uniform sampler Texture_Deluxemap : register(s10),\n"
2979 "#endif\n"
2980 "#ifdef USEREFLECTION\n"
2981 "uniform sampler Texture_Reflection : register(s7),\n"
2982 "#endif\n"
2983 "\n"
2984 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2985 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2986 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2987 "#endif\n"
2988 "#ifdef USEDEFERREDLIGHTMAP\n"
2989 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2990 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2991 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2992 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2993 "#endif\n"
2994 "\n"
2995 "#ifdef USECOLORMAPPING\n"
2996 "uniform half3 Color_Pants : register(c7),\n"
2997 "uniform half3 Color_Shirt : register(c8),\n"
2998 "#endif\n"
2999 "#ifdef USEFOG\n"
3000 "uniform float3 FogColor : register(c16),\n"
3001 "uniform float FogRangeRecip : register(c20),\n"
3002 "uniform float FogPlaneViewDist : register(c19),\n"
3003 "uniform float FogHeightFade : register(c17),\n"
3004 "#endif\n"
3005 "\n"
3006 "#ifdef USEOFFSETMAPPING\n"
3007 "uniform float OffsetMapping_Scale : register(c24),\n"
3008 "#endif\n"
3009 "\n"
3010 "#ifdef USEDEFERREDLIGHTMAP\n"
3011 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3012 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3013 "uniform half3 DeferredMod_Specular : register(c13),\n"
3014 "#endif\n"
3015 "uniform half3 Color_Ambient : register(c3),\n"
3016 "uniform half3 Color_Diffuse : register(c4),\n"
3017 "uniform half3 Color_Specular : register(c5),\n"
3018 "uniform half SpecularPower : register(c36),\n"
3019 "#ifdef USEGLOW\n"
3020 "uniform half3 Color_Glow : register(c6),\n"
3021 "#endif\n"
3022 "uniform half Alpha : register(c0),\n"
3023 "#ifdef USEREFLECTION\n"
3024 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3025 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3026 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3027 "uniform half4 ReflectColor : register(c26),\n"
3028 "#endif\n"
3029 "#ifdef USEREFLECTCUBE\n"
3030 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3031 "uniform sampler Texture_ReflectMask : register(s5),\n"
3032 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3033 "#endif\n"
3034 "#ifdef MODE_LIGHTDIRECTION\n"
3035 "uniform half3 LightColor : register(c21),\n"
3036 "#endif\n"
3037 "#ifdef MODE_LIGHTSOURCE\n"
3038 "uniform half3 LightColor : register(c21),\n"
3039 "#endif\n"
3040 "\n"
3041 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3042 "uniform sampler Texture_Attenuation : register(s9),\n"
3043 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3044 "#endif\n"
3045 "\n"
3046 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3047 "\n"
3048 "#ifdef USESHADOWMAP2D\n"
3049 "# ifdef USESHADOWSAMPLER\n"
3050 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3051 "# else\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# endif\n"
3054 "#endif\n"
3055 "\n"
3056 "#ifdef USESHADOWMAPVSDCT\n"
3057 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3058 "#endif\n"
3059 "\n"
3060 "#if defined(USESHADOWMAP2D)\n"
3061 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3062 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3063 "#endif\n"
3064 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3065 "\n"
3066 "out float4 gl_FragColor : COLOR\n"
3067 ")\n"
3068 "{\n"
3069 "       float2 TexCoord = TexCoordBoth.xy;\n"
3070 "#ifdef USEVERTEXTEXTUREBLEND\n"
3071 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3072 "#endif\n"
3073 "#ifdef USEOFFSETMAPPING\n"
3074 "       // apply offsetmapping\n"
3075 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3076 "#define TexCoord TexCoordOffset\n"
3077 "#endif\n"
3078 "\n"
3079 "       // combine the diffuse textures (base, pants, shirt)\n"
3080 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3081 "#ifdef USEALPHAKILL\n"
3082 "       if (color.a < 0.5)\n"
3083 "               discard;\n"
3084 "#endif\n"
3085 "       color.a *= Alpha;\n"
3086 "#ifdef USECOLORMAPPING\n"
3087 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3088 "#endif\n"
3089 "#ifdef USEVERTEXTEXTUREBLEND\n"
3090 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3091 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3092 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3093 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3094 "       color.a = 1.0;\n"
3095 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3096 "#endif\n"
3097 "\n"
3098 "       // get the surface normal\n"
3099 "#ifdef USEVERTEXTEXTUREBLEND\n"
3100 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3101 "#else\n"
3102 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3103 "#endif\n"
3104 "\n"
3105 "       // get the material colors\n"
3106 "       half3 diffusetex = color.rgb;\n"
3107 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3108 "# ifdef USEVERTEXTEXTUREBLEND\n"
3109 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3110 "# else\n"
3111 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3112 "# endif\n"
3113 "#endif\n"
3114 "\n"
3115 "#ifdef USEREFLECTCUBE\n"
3116 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3117 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3118 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3119 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3120 "#endif\n"
3121 "\n"
3122 "\n"
3123 "\n"
3124 "\n"
3125 "#ifdef MODE_LIGHTSOURCE\n"
3126 "       // light source\n"
3127 "#ifdef USEDIFFUSE\n"
3128 "       half3 lightnormal = half3(normalize(LightVector));\n"
3129 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3130 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3131 "#ifdef USESPECULAR\n"
3132 "#ifdef USEEXACTSPECULARMATH\n"
3133 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3134 "#else\n"
3135 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3136 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3137 "#endif\n"
3138 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3139 "#endif\n"
3140 "#else\n"
3141 "       color.rgb = diffusetex * Color_Ambient;\n"
3142 "#endif\n"
3143 "       color.rgb *= LightColor;\n"
3144 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3145 "#if defined(USESHADOWMAP2D)\n"
3146 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3147 "#ifdef USESHADOWMAPVSDCT\n"
3148 ", Texture_CubeProjection\n"
3149 "#endif\n"
3150 "       ));\n"
3151 "\n"
3152 "#endif\n"
3153 "# ifdef USECUBEFILTER\n"
3154 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3155 "# endif\n"
3156 "\n"
3157 "#ifdef USESHADOWMAP2D\n"
3158 "#ifdef USESHADOWMAPVSDCT\n"
3159 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3160 "#else\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3162 "#endif\n"
3163 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3164 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3165 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3166 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3167 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3168 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3169 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3170 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3171 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3172 "//     color.r = half(shadowmaptc.z);\n"
3173 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = 1;\n"
3176 "//     color.rgb = abs(CubeVector);\n"
3177 "#endif\n"
3178 "//     color.rgb = half3(1,1,1);\n"
3179 "#endif // MODE_LIGHTSOURCE\n"
3180 "\n"
3181 "\n"
3182 "\n"
3183 "\n"
3184 "#ifdef MODE_LIGHTDIRECTION\n"
3185 "#define SHADING\n"
3186 "#ifdef USEDIFFUSE\n"
3187 "       half3 lightnormal = half3(normalize(LightVector));\n"
3188 "#endif\n"
3189 "#define lightcolor LightColor\n"
3190 "#endif // MODE_LIGHTDIRECTION\n"
3191 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3192 "#define SHADING\n"
3193 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3194 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3195 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3196 "       // convert modelspace light vector to tangentspace\n"
3197 "       half3 lightnormal;\n"
3198 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3199 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3200 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3201 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3202 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3203 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3204 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3205 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3206 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3207 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3208 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3209 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3210 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3211 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3212 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3213 "#define SHADING\n"
3214 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3215 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3216 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3217 "#endif\n"
3218 "\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "#ifdef MODE_FAKELIGHT\n"
3223 "#define SHADING\n"
3224 "half3 lightnormal = half3(normalize(EyeVector));\n"
3225 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3226 "#endif // MODE_FAKELIGHT\n"
3227 "\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "#ifdef MODE_LIGHTMAP\n"
3232 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3233 "#endif // MODE_LIGHTMAP\n"
3234 "#ifdef MODE_VERTEXCOLOR\n"
3235 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3236 "#endif // MODE_VERTEXCOLOR\n"
3237 "#ifdef MODE_FLATCOLOR\n"
3238 "       color.rgb = diffusetex * Color_Ambient;\n"
3239 "#endif // MODE_FLATCOLOR\n"
3240 "\n"
3241 "\n"
3242 "\n"
3243 "\n"
3244 "#ifdef SHADING\n"
3245 "# ifdef USEDIFFUSE\n"
3246 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3247 "#  ifdef USESPECULAR\n"
3248 "#   ifdef USEEXACTSPECULARMATH\n"
3249 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3250 "#   else\n"
3251 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3252 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3253 "#   endif\n"
3254 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3255 "#  else\n"
3256 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3257 "#  endif\n"
3258 "# else\n"
3259 "       color.rgb = diffusetex * Color_Ambient;\n"
3260 "# endif\n"
3261 "#endif\n"
3262 "\n"
3263 "#ifdef USESHADOWMAPORTHO\n"
3264 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3265 "#endif\n"
3266 "\n"
3267 "#ifdef USEDEFERREDLIGHTMAP\n"
3268 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3269 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3270 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3271 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3272 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3273 "#endif\n"
3274 "\n"
3275 "#ifdef USEGLOW\n"
3276 "#ifdef USEVERTEXTEXTUREBLEND\n"
3277 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3278 "#else\n"
3279 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3280 "#endif\n"
3281 "#endif\n"
3282 "\n"
3283 "#ifdef USEFOG\n"
3284 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3285 "#endif\n"
3286 "\n"
3287 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3288 "#ifdef USEREFLECTION\n"
3289 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3290 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3291 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3292 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3293 "       // FIXME temporary hack to detect the case that the reflection\n"
3294 "       // gets blackened at edges due to leaving the area that contains actual\n"
3295 "       // content.\n"
3296 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3297 "       // 'appening.\n"
3298 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3299 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3300 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3302 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3303 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3304 "#endif\n"
3305 "\n"
3306 "       gl_FragColor = float4(color);\n"
3307 "}\n"
3308 "#endif // FRAGMENT_SHADER\n"
3309 "\n"
3310 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3311 "#endif // !MODE_DEFERREDGEOMETRY\n"
3312 "#endif // !MODE_WATER\n"
3313 "#endif // !MODE_REFRACTION\n"
3314 "#endif // !MODE_BLOOMBLUR\n"
3315 "#endif // !MODE_GENERIC\n"
3316 "#endif // !MODE_POSTPROCESS\n"
3317 "#endif // !MODE_SHOWDEPTH\n"
3318 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3319 ;
3320
3321 char *glslshaderstring = NULL;
3322 char *cgshaderstring = NULL;
3323 char *hlslshaderstring = NULL;
3324
3325 //=======================================================================================================================================================
3326
3327 typedef struct shaderpermutationinfo_s
3328 {
3329         const char *pretext;
3330         const char *name;
3331 }
3332 shaderpermutationinfo_t;
3333
3334 typedef struct shadermodeinfo_s
3335 {
3336         const char *vertexfilename;
3337         const char *geometryfilename;
3338         const char *fragmentfilename;
3339         const char *pretext;
3340         const char *name;
3341 }
3342 shadermodeinfo_t;
3343
3344 typedef enum shaderpermutation_e
3345 {
3346         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3347         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3348         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3349         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3350         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3351         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3352         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3353         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3354         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3355         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3356         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3357         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3358         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3359         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3360         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3361         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3362         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3363         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3364         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3365         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3366         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3367         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3368         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3369         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3370         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3371         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3372         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3373         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3374         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3375 }
3376 shaderpermutation_t;
3377
3378 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3379 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3380 {
3381         {"#define USEDIFFUSE\n", " diffuse"},
3382         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3383         {"#define USEVIEWTINT\n", " viewtint"},
3384         {"#define USECOLORMAPPING\n", " colormapping"},
3385         {"#define USESATURATION\n", " saturation"},
3386         {"#define USEFOGINSIDE\n", " foginside"},
3387         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3388         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3389         {"#define USEGAMMARAMPS\n", " gammaramps"},
3390         {"#define USECUBEFILTER\n", " cubefilter"},
3391         {"#define USEGLOW\n", " glow"},
3392         {"#define USEBLOOM\n", " bloom"},
3393         {"#define USESPECULAR\n", " specular"},
3394         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3395         {"#define USEREFLECTION\n", " reflection"},
3396         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3397         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3398         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3399         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3400         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3401         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3402         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3403         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3404         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3405         {"#define USEALPHAKILL\n", " alphakill"},
3406         {"#define USEREFLECTCUBE\n", " reflectcube"},
3407         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3408 };
3409
3410 // this enum selects which of the glslshadermodeinfo entries should be used
3411 typedef enum shadermode_e
3412 {
3413         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3414         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3415         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3416         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3417         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3418         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3419         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3420         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3421         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3422         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3423         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3424         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3425         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3426         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3427         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3428         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3429         SHADERMODE_COUNT
3430 }
3431 shadermode_t;
3432
3433 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3434 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3435 {
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3438         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3448         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3451         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3452 };
3453
3454 #ifdef SUPPORTCG
3455 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3456 {
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3467         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3468         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3469         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3470         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3471         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3472         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3473 };
3474 #endif
3475
3476 #ifdef SUPPORTD3D
3477 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3478 {
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3494         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3495 };
3496 #endif
3497
3498 struct r_glsl_permutation_s;
3499 typedef struct r_glsl_permutation_s
3500 {
3501         /// hash lookup data
3502         struct r_glsl_permutation_s *hashnext;
3503         unsigned int mode;
3504         unsigned int permutation;
3505
3506         /// indicates if we have tried compiling this permutation already
3507         qboolean compiled;
3508         /// 0 if compilation failed
3509         int program;
3510         /// locations of detected uniforms in program object, or -1 if not found
3511         int loc_Texture_First;
3512         int loc_Texture_Second;
3513         int loc_Texture_GammaRamps;
3514         int loc_Texture_Normal;
3515         int loc_Texture_Color;
3516         int loc_Texture_Gloss;
3517         int loc_Texture_Glow;
3518         int loc_Texture_SecondaryNormal;
3519         int loc_Texture_SecondaryColor;
3520         int loc_Texture_SecondaryGloss;
3521         int loc_Texture_SecondaryGlow;
3522         int loc_Texture_Pants;
3523         int loc_Texture_Shirt;
3524         int loc_Texture_FogHeightTexture;
3525         int loc_Texture_FogMask;
3526         int loc_Texture_Lightmap;
3527         int loc_Texture_Deluxemap;
3528         int loc_Texture_Attenuation;
3529         int loc_Texture_Cube;
3530         int loc_Texture_Refraction;
3531         int loc_Texture_Reflection;
3532         int loc_Texture_ShadowMap2D;
3533         int loc_Texture_CubeProjection;
3534         int loc_Texture_ScreenDepth;
3535         int loc_Texture_ScreenNormalMap;
3536         int loc_Texture_ScreenDiffuse;
3537         int loc_Texture_ScreenSpecular;
3538         int loc_Texture_ReflectMask;
3539         int loc_Texture_ReflectCube;
3540         int loc_Alpha;
3541         int loc_BloomBlur_Parameters;
3542         int loc_ClientTime;
3543         int loc_Color_Ambient;
3544         int loc_Color_Diffuse;
3545         int loc_Color_Specular;
3546         int loc_Color_Glow;
3547         int loc_Color_Pants;
3548         int loc_Color_Shirt;
3549         int loc_DeferredColor_Ambient;
3550         int loc_DeferredColor_Diffuse;
3551         int loc_DeferredColor_Specular;
3552         int loc_DeferredMod_Diffuse;
3553         int loc_DeferredMod_Specular;
3554         int loc_DistortScaleRefractReflect;
3555         int loc_EyePosition;
3556         int loc_FogColor;
3557         int loc_FogHeightFade;
3558         int loc_FogPlane;
3559         int loc_FogPlaneViewDist;
3560         int loc_FogRangeRecip;
3561         int loc_LightColor;
3562         int loc_LightDir;
3563         int loc_LightPosition;
3564         int loc_OffsetMapping_Scale;
3565         int loc_PixelSize;
3566         int loc_ReflectColor;
3567         int loc_ReflectFactor;
3568         int loc_ReflectOffset;
3569         int loc_RefractColor;
3570         int loc_Saturation;
3571         int loc_ScreenCenterRefractReflect;
3572         int loc_ScreenScaleRefractReflect;
3573         int loc_ScreenToDepth;
3574         int loc_ShadowMap_Parameters;
3575         int loc_ShadowMap_TextureScale;
3576         int loc_SpecularPower;
3577         int loc_UserVec1;
3578         int loc_UserVec2;
3579         int loc_UserVec3;
3580         int loc_UserVec4;
3581         int loc_ViewTintColor;
3582         int loc_ViewToLight;
3583         int loc_ModelToLight;
3584         int loc_TexMatrix;
3585         int loc_BackgroundTexMatrix;
3586         int loc_ModelViewProjectionMatrix;
3587         int loc_ModelViewMatrix;
3588         int loc_PixelToScreenTexCoord;
3589         int loc_ModelToReflectCube;
3590         int loc_ShadowMapMatrix;
3591         int loc_BloomColorSubtract;
3592         int loc_NormalmapScrollBlend;
3593 }
3594 r_glsl_permutation_t;
3595
3596 #define SHADERPERMUTATION_HASHSIZE 256
3597
3598
3599 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3600 // these can NOT degrade! only use for simple stuff
3601 enum
3602 {
3603         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3604         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3605         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3606         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3607         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3608         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3609 };
3610 #define SHADERSTATICPARMS_COUNT 6
3611
3612 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3613 static int shaderstaticparms_count = 0;
3614
3615 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3616 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3617 qboolean R_CompileShader_CheckStaticParms(void)
3618 {
3619         static int r_compileshader_staticparms_save[1];
3620         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3621         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3622
3623         // detect all
3624         if (r_glsl_saturation_redcompensate.integer)
3625                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3626         if (r_shadow_glossexact.integer)
3627                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3628         if (r_glsl_postprocess.integer)
3629         {
3630                 if (r_glsl_postprocess_uservec1_enable.integer)
3631                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3632                 if (r_glsl_postprocess_uservec2_enable.integer)
3633                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3634                 if (r_glsl_postprocess_uservec3_enable.integer)
3635                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3636                 if (r_glsl_postprocess_uservec4_enable.integer)
3637                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3638         }
3639         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3640 }
3641
3642 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3643         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3644                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3645         else \
3646                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3647 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3648 {
3649         shaderstaticparms_count = 0;
3650
3651         // emit all
3652         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3653         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3654         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3655         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3656         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3657         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3658 }
3659
3660 /// information about each possible shader permutation
3661 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3662 /// currently selected permutation
3663 r_glsl_permutation_t *r_glsl_permutation;
3664 /// storage for permutations linked in the hash table
3665 memexpandablearray_t r_glsl_permutationarray;
3666
3667 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3668 {
3669         //unsigned int hashdepth = 0;
3670         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3671         r_glsl_permutation_t *p;
3672         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3673         {
3674                 if (p->mode == mode && p->permutation == permutation)
3675                 {
3676                         //if (hashdepth > 10)
3677                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3678                         return p;
3679                 }
3680                 //hashdepth++;
3681         }
3682         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3683         p->mode = mode;
3684         p->permutation = permutation;
3685         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3686         r_glsl_permutationhash[mode][hashindex] = p;
3687         //if (hashdepth > 10)
3688         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3689         return p;
3690 }
3691
3692 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3693 {
3694         char *shaderstring;
3695         if (!filename || !filename[0])
3696                 return NULL;
3697         if (!strcmp(filename, "glsl/default.glsl"))
3698         {
3699                 if (!glslshaderstring)
3700                 {
3701                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3702                         if (glslshaderstring)
3703                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3704                         else
3705                                 glslshaderstring = (char *)builtinshaderstring;
3706                 }
3707                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3708                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3709                 return shaderstring;
3710         }
3711         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3712         if (shaderstring)
3713         {
3714                 if (printfromdisknotice)
3715                         Con_DPrintf("from disk %s... ", filename);
3716                 return shaderstring;
3717         }
3718         return shaderstring;
3719 }
3720
3721 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3722 {
3723         int i;
3724         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3725         char *vertexstring, *geometrystring, *fragmentstring;
3726         char permutationname[256];
3727         int vertstrings_count = 0;
3728         int geomstrings_count = 0;
3729         int fragstrings_count = 0;
3730         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3731         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3733
3734         if (p->compiled)
3735                 return;
3736         p->compiled = true;
3737         p->program = 0;
3738
3739         permutationname[0] = 0;
3740         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3741         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3742         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3743
3744         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3745
3746         // the first pretext is which type of shader to compile as
3747         // (later these will all be bound together as a program object)
3748         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3749         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3750         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3751
3752         // the second pretext is the mode (for example a light source)
3753         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3754         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3755         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3756         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3757
3758         // now add all the permutation pretexts
3759         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3760         {
3761                 if (permutation & (1<<i))
3762                 {
3763                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3764                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3765                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3766                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3767                 }
3768                 else
3769                 {
3770                         // keep line numbers correct
3771                         vertstrings_list[vertstrings_count++] = "\n";
3772                         geomstrings_list[geomstrings_count++] = "\n";
3773                         fragstrings_list[fragstrings_count++] = "\n";
3774                 }
3775         }
3776
3777         // add static parms
3778         R_CompileShader_AddStaticParms(mode, permutation);
3779         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3780         vertstrings_count += shaderstaticparms_count;
3781         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3782         geomstrings_count += shaderstaticparms_count;
3783         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3784         fragstrings_count += shaderstaticparms_count;
3785
3786         // now append the shader text itself
3787         vertstrings_list[vertstrings_count++] = vertexstring;
3788         geomstrings_list[geomstrings_count++] = geometrystring;
3789         fragstrings_list[fragstrings_count++] = fragmentstring;
3790
3791         // if any sources were NULL, clear the respective list
3792         if (!vertexstring)
3793                 vertstrings_count = 0;
3794         if (!geometrystring)
3795                 geomstrings_count = 0;
3796         if (!fragmentstring)
3797                 fragstrings_count = 0;
3798
3799         // compile the shader program
3800         if (vertstrings_count + geomstrings_count + fragstrings_count)
3801                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3802         if (p->program)
3803         {
3804                 CHECKGLERROR
3805                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3806                 // look up all the uniform variable names we care about, so we don't
3807                 // have to look them up every time we set them
3808
3809                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3810                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3811                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3812                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3813                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3814                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3815                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3816                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3817                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3818                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3819                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3820                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3821                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3822                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3823                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3824                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3825                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3826                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3827                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3828                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3829                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3830                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3831                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3832                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3833                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3834                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3835                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3836                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3837                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3838                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3839                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3840                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3841                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3842                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3843                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3844                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3845                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3846                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3847                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3848                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3849                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3850                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3851                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3852                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3853                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3854                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3855                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3856                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3857                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3858                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3859                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3860                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3861                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3862                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3863                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3864                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3865                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3866                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3867                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3868                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3869                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3870                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3871                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3872                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3873                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3874                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3875                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3876                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3877                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3878                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3879                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3880                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3881                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3882                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3883                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3884                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3885                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3886                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3887                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3888                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3889                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3890                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3891                 // initialize the samplers to refer to the texture units we use
3892                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3893                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3894                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3895                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3896                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3897                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3898                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3899                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3900                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3901                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3902                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3903                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3904                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3905                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3906                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3907                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3908                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3909                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3910                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3911                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3912                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3913                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3914                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3915                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3916                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3917                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3918                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3919                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3920                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3921                 CHECKGLERROR
3922                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3923         }
3924         else
3925                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3926
3927         // free the strings
3928         if (vertexstring)
3929                 Mem_Free(vertexstring);
3930         if (geometrystring)
3931                 Mem_Free(geometrystring);
3932         if (fragmentstring)
3933                 Mem_Free(fragmentstring);
3934 }
3935
3936 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3937 {
3938         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3939         if (r_glsl_permutation != perm)
3940         {
3941                 r_glsl_permutation = perm;
3942                 if (!r_glsl_permutation->program)
3943                 {
3944                         if (!r_glsl_permutation->compiled)
3945                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3946                         if (!r_glsl_permutation->program)
3947                         {
3948                                 // remove features until we find a valid permutation
3949                                 int i;
3950                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3951                                 {
3952                                         // reduce i more quickly whenever it would not remove any bits
3953                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3954                                         if (!(permutation & j))
3955                                                 continue;
3956                                         permutation -= j;
3957                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3958                                         if (!r_glsl_permutation->compiled)
3959                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3960                                         if (r_glsl_permutation->program)
3961                                                 break;
3962                                 }
3963                                 if (i >= SHADERPERMUTATION_COUNT)
3964                                 {
3965                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3966                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3967                                         qglUseProgramObjectARB(0);CHECKGLERROR
3968                                         return; // no bit left to clear, entire mode is broken
3969                                 }
3970                         }
3971                 }
3972                 CHECKGLERROR
3973                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3974         }
3975         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3976         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3977         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3978 }
3979
3980 #ifdef SUPPORTCG
3981 #include <Cg/cgGL.h>
3982 struct r_cg_permutation_s;
3983 typedef struct r_cg_permutation_s
3984 {
3985         /// hash lookup data
3986         struct r_cg_permutation_s *hashnext;
3987         unsigned int mode;
3988         unsigned int permutation;
3989
3990         /// indicates if we have tried compiling this permutation already
3991         qboolean compiled;
3992         /// 0 if compilation failed
3993         CGprogram vprogram;
3994         CGprogram fprogram;
3995         /// locations of detected parameters in programs, or NULL if not found
3996         CGparameter vp_EyePosition;
3997         CGparameter vp_FogPlane;
3998         CGparameter vp_LightDir;
3999         CGparameter vp_LightPosition;
4000         CGparameter vp_ModelToLight;
4001         CGparameter vp_TexMatrix;
4002         CGparameter vp_BackgroundTexMatrix;
4003         CGparameter vp_ModelViewProjectionMatrix;
4004         CGparameter vp_ModelViewMatrix;
4005         CGparameter vp_ShadowMapMatrix;
4006
4007         CGparameter fp_Texture_First;
4008         CGparameter fp_Texture_Second;
4009         CGparameter fp_Texture_GammaRamps;
4010         CGparameter fp_Texture_Normal;
4011         CGparameter fp_Texture_Color;
4012         CGparameter fp_Texture_Gloss;
4013         CGparameter fp_Texture_Glow;
4014         CGparameter fp_Texture_SecondaryNormal;
4015         CGparameter fp_Texture_SecondaryColor;
4016         CGparameter fp_Texture_SecondaryGloss;
4017         CGparameter fp_Texture_SecondaryGlow;
4018         CGparameter fp_Texture_Pants;
4019         CGparameter fp_Texture_Shirt;
4020         CGparameter fp_Texture_FogHeightTexture;
4021         CGparameter fp_Texture_FogMask;
4022         CGparameter fp_Texture_Lightmap;
4023         CGparameter fp_Texture_Deluxemap;
4024         CGparameter fp_Texture_Attenuation;
4025         CGparameter fp_Texture_Cube;
4026         CGparameter fp_Texture_Refraction;
4027         CGparameter fp_Texture_Reflection;
4028         CGparameter fp_Texture_ShadowMap2D;
4029         CGparameter fp_Texture_CubeProjection;
4030         CGparameter fp_Texture_ScreenDepth;
4031         CGparameter fp_Texture_ScreenNormalMap;
4032         CGparameter fp_Texture_ScreenDiffuse;
4033         CGparameter fp_Texture_ScreenSpecular;
4034         CGparameter fp_Texture_ReflectMask;
4035         CGparameter fp_Texture_ReflectCube;
4036         CGparameter fp_Alpha;
4037         CGparameter fp_BloomBlur_Parameters;
4038         CGparameter fp_ClientTime;
4039         CGparameter fp_Color_Ambient;
4040         CGparameter fp_Color_Diffuse;
4041         CGparameter fp_Color_Specular;
4042         CGparameter fp_Color_Glow;
4043         CGparameter fp_Color_Pants;
4044         CGparameter fp_Color_Shirt;
4045         CGparameter fp_DeferredColor_Ambient;
4046         CGparameter fp_DeferredColor_Diffuse;
4047         CGparameter fp_DeferredColor_Specular;
4048         CGparameter fp_DeferredMod_Diffuse;
4049         CGparameter fp_DeferredMod_Specular;
4050         CGparameter fp_DistortScaleRefractReflect;
4051         CGparameter fp_EyePosition;
4052         CGparameter fp_FogColor;
4053         CGparameter fp_FogHeightFade;
4054         CGparameter fp_FogPlane;
4055         CGparameter fp_FogPlaneViewDist;
4056         CGparameter fp_FogRangeRecip;
4057         CGparameter fp_LightColor;
4058         CGparameter fp_LightDir;
4059         CGparameter fp_LightPosition;
4060         CGparameter fp_OffsetMapping_Scale;
4061         CGparameter fp_PixelSize;
4062         CGparameter fp_ReflectColor;
4063         CGparameter fp_ReflectFactor;
4064         CGparameter fp_ReflectOffset;
4065         CGparameter fp_RefractColor;
4066         CGparameter fp_Saturation;
4067         CGparameter fp_ScreenCenterRefractReflect;
4068         CGparameter fp_ScreenScaleRefractReflect;
4069         CGparameter fp_ScreenToDepth;
4070         CGparameter fp_ShadowMap_Parameters;
4071         CGparameter fp_ShadowMap_TextureScale;
4072         CGparameter fp_SpecularPower;
4073         CGparameter fp_UserVec1;
4074         CGparameter fp_UserVec2;
4075         CGparameter fp_UserVec3;
4076         CGparameter fp_UserVec4;
4077         CGparameter fp_ViewTintColor;
4078         CGparameter fp_ViewToLight;
4079         CGparameter fp_PixelToScreenTexCoord;
4080         CGparameter fp_ModelToReflectCube;
4081         CGparameter fp_BloomColorSubtract;
4082         CGparameter fp_NormalmapScrollBlend;
4083 }
4084 r_cg_permutation_t;
4085
4086 /// information about each possible shader permutation
4087 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4088 /// currently selected permutation
4089 r_cg_permutation_t *r_cg_permutation;
4090 /// storage for permutations linked in the hash table
4091 memexpandablearray_t r_cg_permutationarray;
4092
4093 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4094
4095 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4096 {
4097         //unsigned int hashdepth = 0;
4098         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4099         r_cg_permutation_t *p;
4100         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4101         {
4102                 if (p->mode == mode && p->permutation == permutation)
4103                 {
4104                         //if (hashdepth > 10)
4105                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4106                         return p;
4107                 }
4108                 //hashdepth++;
4109         }
4110         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4111         p->mode = mode;
4112         p->permutation = permutation;
4113         p->hashnext = r_cg_permutationhash[mode][hashindex];
4114         r_cg_permutationhash[mode][hashindex] = p;
4115         //if (hashdepth > 10)
4116         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4117         return p;
4118 }
4119
4120 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4121 {
4122         char *shaderstring;
4123         if (!filename || !filename[0])
4124                 return NULL;
4125         if (!strcmp(filename, "cg/default.cg"))
4126         {
4127                 if (!cgshaderstring)
4128                 {
4129                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4130                         if (cgshaderstring)
4131                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4132                         else
4133                                 cgshaderstring = (char *)builtincgshaderstring;
4134                 }
4135                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4136                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4137                 return shaderstring;
4138         }
4139         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4140         if (shaderstring)
4141         {
4142                 if (printfromdisknotice)
4143                         Con_DPrintf("from disk %s... ", filename);
4144                 return shaderstring;
4145         }
4146         return shaderstring;
4147 }
4148
4149 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4150 {
4151         // TODO: load or create .fp and .vp shader files
4152 }
4153
4154 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4155 {
4156         int i;
4157         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4158         int vertstring_length = 0;
4159         int geomstring_length = 0;
4160         int fragstring_length = 0;
4161         char *t;
4162         char *vertexstring, *geometrystring, *fragmentstring;
4163         char *vertstring, *geomstring, *fragstring;
4164         char permutationname[256];
4165         char cachename[256];
4166         CGprofile vertexProfile;
4167         CGprofile fragmentProfile;
4168         int vertstrings_count = 0;
4169         int geomstrings_count = 0;
4170         int fragstrings_count = 0;
4171         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4172         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4174
4175         if (p->compiled)
4176                 return;
4177         p->compiled = true;
4178         p->vprogram = NULL;
4179         p->fprogram = NULL;
4180
4181         permutationname[0] = 0;
4182         cachename[0] = 0;
4183         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4184         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4185         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4186
4187         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4188         strlcat(cachename, "cg/", sizeof(cachename));
4189
4190         // the first pretext is which type of shader to compile as
4191         // (later these will all be bound together as a program object)
4192         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4193         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4194         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4195
4196         // the second pretext is the mode (for example a light source)
4197         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4198         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4199         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4200         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4201         strlcat(cachename, modeinfo->name, sizeof(cachename));
4202
4203         // now add all the permutation pretexts
4204         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4205         {
4206                 if (permutation & (1<<i))
4207                 {
4208                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4209                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4211                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4212                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4213                 }
4214                 else
4215                 {
4216                         // keep line numbers correct
4217                         vertstrings_list[vertstrings_count++] = "\n";
4218                         geomstrings_list[geomstrings_count++] = "\n";
4219                         fragstrings_list[fragstrings_count++] = "\n";
4220                 }
4221         }
4222
4223         // add static parms
4224         R_CompileShader_AddStaticParms(mode, permutation);
4225         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4226         vertstrings_count += shaderstaticparms_count;
4227         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4228         geomstrings_count += shaderstaticparms_count;
4229         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4230         fragstrings_count += shaderstaticparms_count;
4231
4232         // replace spaces in the cachename with _ characters
4233         for (i = 0;cachename[i];i++)
4234                 if (cachename[i] == ' ')
4235                         cachename[i] = '_';
4236
4237         // now append the shader text itself
4238         vertstrings_list[vertstrings_count++] = vertexstring;
4239         geomstrings_list[geomstrings_count++] = geometrystring;
4240         fragstrings_list[fragstrings_count++] = fragmentstring;
4241
4242         // if any sources were NULL, clear the respective list
4243         if (!vertexstring)
4244                 vertstrings_count = 0;
4245         if (!geometrystring)
4246                 geomstrings_count = 0;
4247         if (!fragmentstring)
4248                 fragstrings_count = 0;
4249
4250         vertstring_length = 0;
4251         for (i = 0;i < vertstrings_count;i++)
4252                 vertstring_length += strlen(vertstrings_list[i]);
4253         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4254         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4255                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4256
4257         geomstring_length = 0;
4258         for (i = 0;i < geomstrings_count;i++)
4259                 geomstring_length += strlen(geomstrings_list[i]);
4260         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4261         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4262                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4263
4264         fragstring_length = 0;
4265         for (i = 0;i < fragstrings_count;i++)
4266                 fragstring_length += strlen(fragstrings_list[i]);
4267         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4268         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4269                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4270
4271         CHECKGLERROR
4272         CHECKCGERROR
4273         //vertexProfile = CG_PROFILE_ARBVP1;
4274         //fragmentProfile = CG_PROFILE_ARBFP1;
4275         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4276         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4277         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4278         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4279         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4280         CHECKGLERROR
4281
4282         // try to load the cached shader, or generate one
4283         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4284
4285         // if caching failed, do a dynamic compile for now
4286         CHECKCGERROR
4287         if (vertstring[0] && !p->vprogram)
4288                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4289         CHECKCGERROR
4290         if (fragstring[0] && !p->fprogram)
4291                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4292         CHECKCGERROR
4293
4294         // look up all the uniform variable names we care about, so we don't
4295         // have to look them up every time we set them
4296         if (p->vprogram)
4297         {
4298                 CHECKCGERROR
4299                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4300                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4301                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4302                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4303                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4304                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4305                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4306                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4307                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4308                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4309                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4310                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4311                 CHECKCGERROR
4312         }
4313         if (p->fprogram)
4314         {
4315                 CHECKCGERROR
4316                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4317                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4318                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4319                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4320                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4321                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4322                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4323                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4324                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4325                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4326                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4327                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4328                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4329                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4330                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4331                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4332                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4333                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4334                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4335                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4336                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4337                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4338                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4339                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4340                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4341                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4342                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4343                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4344                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4345                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4346                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4347                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4348                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4349                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4350                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4351                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4352                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4353                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4354                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4355                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4356                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4357                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4358                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4359                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4360                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4361                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4362                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4363                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4364                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4365                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4366                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4367                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4368                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4369                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4370                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4371                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4372                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4373                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4374                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4375                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4376                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4377                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4378                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4379                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4380                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4381                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4382                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4383                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4384                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4385                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4386                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4387                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4388                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4389                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4390                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4391                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4392                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4393                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4394                 CHECKCGERROR
4395         }
4396
4397         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4398                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4399         else
4400                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4401
4402         // free the strings
4403         if (vertstring)
4404                 Mem_Free(vertstring);
4405         if (geomstring)
4406                 Mem_Free(geomstring);
4407         if (fragstring)
4408                 Mem_Free(fragstring);
4409         if (vertexstring)
4410                 Mem_Free(vertexstring);
4411         if (geometrystring)
4412                 Mem_Free(geometrystring);
4413         if (fragmentstring)
4414                 Mem_Free(fragmentstring);
4415 }
4416
4417 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4418 {
4419         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4420         CHECKGLERROR
4421         CHECKCGERROR
4422         if (r_cg_permutation != perm)
4423         {
4424                 r_cg_permutation = perm;
4425                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4426                 {
4427                         if (!r_cg_permutation->compiled)
4428                                 R_CG_CompilePermutation(perm, mode, permutation);
4429                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4430                         {
4431                                 // remove features until we find a valid permutation
4432                                 int i;
4433                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4434                                 {
4435                                         // reduce i more quickly whenever it would not remove any bits
4436                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4437                                         if (!(permutation & j))
4438                                                 continue;
4439                                         permutation -= j;
4440                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4441                                         if (!r_cg_permutation->compiled)
4442                                                 R_CG_CompilePermutation(perm, mode, permutation);
4443                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4444                                                 break;
4445                                 }
4446                                 if (i >= SHADERPERMUTATION_COUNT)
4447                                 {
4448                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4449                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4450                                         return; // no bit left to clear, entire mode is broken
4451                                 }
4452                         }
4453                 }
4454                 CHECKGLERROR
4455                 CHECKCGERROR
4456                 if (r_cg_permutation->vprogram)
4457                 {
4458                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4459                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4460                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4461                 }
4462                 else
4463                 {
4464                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4465                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466                 }
4467                 if (r_cg_permutation->fprogram)
4468                 {
4469                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4470                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4471                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4472                 }
4473                 else
4474                 {
4475                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4476                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4477                 }
4478         }
4479         CHECKCGERROR
4480         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4481         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4482         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4483 }
4484
4485 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4486 {
4487         cgGLSetTextureParameter(param, R_GetTexture(tex));
4488         cgGLEnableTextureParameter(param);
4489 }
4490 #endif
4491
4492 #ifdef SUPPORTD3D
4493
4494 #ifdef SUPPORTD3D
4495 #include <d3d9.h>
4496 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4497 extern D3DCAPS9 vid_d3d9caps;
4498 #endif
4499
4500 struct r_hlsl_permutation_s;
4501 typedef struct r_hlsl_permutation_s
4502 {
4503         /// hash lookup data
4504         struct r_hlsl_permutation_s *hashnext;
4505         unsigned int mode;
4506         unsigned int permutation;
4507
4508         /// indicates if we have tried compiling this permutation already
4509         qboolean compiled;
4510         /// NULL if compilation failed
4511         IDirect3DVertexShader9 *vertexshader;
4512         IDirect3DPixelShader9 *pixelshader;
4513 }
4514 r_hlsl_permutation_t;
4515
4516 typedef enum D3DVSREGISTER_e
4517 {
4518         D3DVSREGISTER_TexMatrix = 0, // float4x4
4519         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4520         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4521         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4522         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4523         D3DVSREGISTER_ModelToLight = 20, // float4x4
4524         D3DVSREGISTER_EyePosition = 24,
4525         D3DVSREGISTER_FogPlane = 25,
4526         D3DVSREGISTER_LightDir = 26,
4527         D3DVSREGISTER_LightPosition = 27,
4528 }
4529 D3DVSREGISTER_t;
4530
4531 typedef enum D3DPSREGISTER_e
4532 {
4533         D3DPSREGISTER_Alpha = 0,
4534         D3DPSREGISTER_BloomBlur_Parameters = 1,
4535         D3DPSREGISTER_ClientTime = 2,
4536         D3DPSREGISTER_Color_Ambient = 3,
4537         D3DPSREGISTER_Color_Diffuse = 4,
4538         D3DPSREGISTER_Color_Specular = 5,
4539         D3DPSREGISTER_Color_Glow = 6,
4540         D3DPSREGISTER_Color_Pants = 7,
4541         D3DPSREGISTER_Color_Shirt = 8,
4542         D3DPSREGISTER_DeferredColor_Ambient = 9,
4543         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4544         D3DPSREGISTER_DeferredColor_Specular = 11,
4545         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4546         D3DPSREGISTER_DeferredMod_Specular = 13,
4547         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4548         D3DPSREGISTER_EyePosition = 15, // unused
4549         D3DPSREGISTER_FogColor = 16,
4550         D3DPSREGISTER_FogHeightFade = 17,
4551         D3DPSREGISTER_FogPlane = 18,
4552         D3DPSREGISTER_FogPlaneViewDist = 19,
4553         D3DPSREGISTER_FogRangeRecip = 20,
4554         D3DPSREGISTER_LightColor = 21,
4555         D3DPSREGISTER_LightDir = 22, // unused
4556         D3DPSREGISTER_LightPosition = 23,
4557         D3DPSREGISTER_OffsetMapping_Scale = 24,
4558         D3DPSREGISTER_PixelSize = 25,
4559         D3DPSREGISTER_ReflectColor = 26,
4560         D3DPSREGISTER_ReflectFactor = 27,
4561         D3DPSREGISTER_ReflectOffset = 28,
4562         D3DPSREGISTER_RefractColor = 29,
4563         D3DPSREGISTER_Saturation = 30,
4564         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4565         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4566         D3DPSREGISTER_ScreenToDepth = 33,
4567         D3DPSREGISTER_ShadowMap_Parameters = 34,
4568         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4569         D3DPSREGISTER_SpecularPower = 36,
4570         D3DPSREGISTER_UserVec1 = 37,
4571         D3DPSREGISTER_UserVec2 = 38,
4572         D3DPSREGISTER_UserVec3 = 39,
4573         D3DPSREGISTER_UserVec4 = 40,
4574         D3DPSREGISTER_ViewTintColor = 41,
4575         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4576         D3DPSREGISTER_BloomColorSubtract = 43,
4577         D3DPSREGISTER_ViewToLight = 44, // float4x4
4578         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4579         D3DPSREGISTER_NormalmapScrollBlend = 52,
4580         // next at 53
4581 }
4582 D3DPSREGISTER_t;
4583
4584 /// information about each possible shader permutation
4585 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4586 /// currently selected permutation
4587 r_hlsl_permutation_t *r_hlsl_permutation;
4588 /// storage for permutations linked in the hash table
4589 memexpandablearray_t r_hlsl_permutationarray;
4590
4591 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4592 {
4593         //unsigned int hashdepth = 0;
4594         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4595         r_hlsl_permutation_t *p;
4596         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4597         {
4598                 if (p->mode == mode && p->permutation == permutation)
4599                 {
4600                         //if (hashdepth > 10)
4601                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4602                         return p;
4603                 }
4604                 //hashdepth++;
4605         }
4606         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4607         p->mode = mode;
4608         p->permutation = permutation;
4609         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4610         r_hlsl_permutationhash[mode][hashindex] = p;
4611         //if (hashdepth > 10)
4612         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4613         return p;
4614 }
4615
4616 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4617 {
4618         char *shaderstring;
4619         if (!filename || !filename[0])
4620                 return NULL;
4621         if (!strcmp(filename, "hlsl/default.hlsl"))
4622         {
4623                 if (!hlslshaderstring)
4624                 {
4625                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4626                         if (hlslshaderstring)
4627                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4628                         else
4629                                 hlslshaderstring = (char *)builtincgshaderstring;
4630                 }
4631                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4632                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4633                 return shaderstring;
4634         }
4635         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4636         if (shaderstring)
4637         {
4638                 if (printfromdisknotice)
4639                         Con_DPrintf("from disk %s... ", filename);
4640                 return shaderstring;
4641         }
4642         return shaderstring;
4643 }
4644
4645 #include <d3dx9.h>
4646 //#include <d3dx9shader.h>
4647 //#include <d3dx9mesh.h>
4648
4649 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4650 {
4651         DWORD *vsbin = NULL;
4652         DWORD *psbin = NULL;
4653         fs_offset_t vsbinsize;
4654         fs_offset_t psbinsize;
4655 //      IDirect3DVertexShader9 *vs = NULL;
4656 //      IDirect3DPixelShader9 *ps = NULL;
4657         ID3DXBuffer *vslog = NULL;
4658         ID3DXBuffer *vsbuffer = NULL;
4659         ID3DXConstantTable *vsconstanttable = NULL;
4660         ID3DXBuffer *pslog = NULL;
4661         ID3DXBuffer *psbuffer = NULL;
4662         ID3DXConstantTable *psconstanttable = NULL;
4663         int vsresult = 0;
4664         int psresult = 0;
4665         char temp[MAX_INPUTLINE];
4666         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4667         qboolean debugshader = gl_paranoid.integer != 0;
4668         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4669         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4670         if (!debugshader)
4671         {
4672                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4673                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4674         }
4675         if ((!vsbin && vertstring) || (!psbin && fragstring))
4676         {
4677                 const char* dllnames_d3dx9 [] =
4678                 {
4679                         "d3dx9_43.dll",
4680                         "d3dx9_42.dll",
4681                         "d3dx9_41.dll",
4682                         "d3dx9_40.dll",
4683                         "d3dx9_39.dll",
4684                         "d3dx9_38.dll",
4685                         "d3dx9_37.dll",
4686                         "d3dx9_36.dll",
4687                         "d3dx9_35.dll",
4688                         "d3dx9_34.dll",
4689                         "d3dx9_33.dll",
4690                         "d3dx9_32.dll",
4691                         "d3dx9_31.dll",
4692                         "d3dx9_30.dll",
4693                         "d3dx9_29.dll",
4694                         "d3dx9_28.dll",
4695                         "d3dx9_27.dll",
4696                         "d3dx9_26.dll",
4697                         "d3dx9_25.dll",
4698                         "d3dx9_24.dll",
4699                         NULL
4700                 };
4701                 dllhandle_t d3dx9_dll = NULL;
4702                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4703                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4704                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4705                 dllfunction_t d3dx9_dllfuncs[] =
4706                 {
4707                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4708                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4709                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4710                         {NULL, NULL}
4711                 };
4712                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4713                 {
4714                         DWORD shaderflags = 0;
4715                         if (debugshader)
4716                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4717                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4718                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4719                         if (vertstring && vertstring[0])
4720                         {
4721                                 if (debugshader)
4722                                 {
4723 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4724 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4725                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4726                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4727                                 }
4728                                 else
4729                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4730                                 if (vsbuffer)
4731                                 {
4732                                         vsbinsize = vsbuffer->GetBufferSize();
4733                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4734                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4735                                         vsbuffer->Release();
4736                                 }
4737                                 if (vslog)
4738                                 {
4739                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4740                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4741                                         vslog->Release();
4742                                 }
4743                         }
4744                         if (fragstring && fragstring[0])
4745                         {
4746                                 if (debugshader)
4747                                 {
4748 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4749 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4750                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4751                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4752                                 }
4753                                 else
4754                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4755                                 if (psbuffer)
4756                                 {
4757                                         psbinsize = psbuffer->GetBufferSize();
4758                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4759                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4760                                         psbuffer->Release();
4761                                 }
4762                                 if (pslog)
4763                                 {
4764                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4765                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4766                                         pslog->Release();
4767                                 }
4768                         }
4769                         Sys_UnloadLibrary(&d3dx9_dll);
4770                 }
4771                 else
4772                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4773         }
4774         if (vsbin && psbin)
4775         {
4776                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4777                 if (FAILED(vsresult))
4778                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4779                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4780                 if (FAILED(psresult))
4781                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4782         }
4783         // free the shader data
4784         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4785         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4786 }
4787
4788 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4789 {
4790         int i;
4791         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4792         int vertstring_length = 0;
4793         int geomstring_length = 0;
4794         int fragstring_length = 0;
4795         char *t;
4796         char *vertexstring, *geometrystring, *fragmentstring;
4797         char *vertstring, *geomstring, *fragstring;
4798         char permutationname[256];
4799         char cachename[256];
4800         int vertstrings_count = 0;
4801         int geomstrings_count = 0;
4802         int fragstrings_count = 0;
4803         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4804         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4806
4807         if (p->compiled)
4808                 return;
4809         p->compiled = true;
4810         p->vertexshader = NULL;
4811         p->pixelshader = NULL;
4812
4813         permutationname[0] = 0;
4814         cachename[0] = 0;
4815         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4816         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4817         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4818
4819         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4820         strlcat(cachename, "hlsl/", sizeof(cachename));
4821
4822         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4823         vertstrings_count = 0;
4824         geomstrings_count = 0;
4825         fragstrings_count = 0;
4826         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4827         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4828         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4829
4830         // the first pretext is which type of shader to compile as
4831         // (later these will all be bound together as a program object)
4832         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4833         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4834         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4835
4836         // the second pretext is the mode (for example a light source)
4837         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4838         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4839         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4840         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4841         strlcat(cachename, modeinfo->name, sizeof(cachename));
4842
4843         // now add all the permutation pretexts
4844         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4845         {
4846                 if (permutation & (1<<i))
4847                 {
4848                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4849                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4851                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4852                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4853                 }
4854                 else
4855                 {
4856                         // keep line numbers correct
4857                         vertstrings_list[vertstrings_count++] = "\n";
4858                         geomstrings_list[geomstrings_count++] = "\n";
4859                         fragstrings_list[fragstrings_count++] = "\n";
4860                 }
4861         }
4862
4863         // add static parms
4864         R_CompileShader_AddStaticParms(mode, permutation);
4865         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4866         vertstrings_count += shaderstaticparms_count;
4867         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4868         geomstrings_count += shaderstaticparms_count;
4869         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4870         fragstrings_count += shaderstaticparms_count;
4871
4872         // replace spaces in the cachename with _ characters
4873         for (i = 0;cachename[i];i++)
4874                 if (cachename[i] == ' ')
4875                         cachename[i] = '_';
4876
4877         // now append the shader text itself
4878         vertstrings_list[vertstrings_count++] = vertexstring;
4879         geomstrings_list[geomstrings_count++] = geometrystring;
4880         fragstrings_list[fragstrings_count++] = fragmentstring;
4881
4882         // if any sources were NULL, clear the respective list
4883         if (!vertexstring)
4884                 vertstrings_count = 0;
4885         if (!geometrystring)
4886                 geomstrings_count = 0;
4887         if (!fragmentstring)
4888                 fragstrings_count = 0;
4889
4890         vertstring_length = 0;
4891         for (i = 0;i < vertstrings_count;i++)
4892                 vertstring_length += strlen(vertstrings_list[i]);
4893         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4894         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4895                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4896
4897         geomstring_length = 0;
4898         for (i = 0;i < geomstrings_count;i++)
4899                 geomstring_length += strlen(geomstrings_list[i]);
4900         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4901         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4902                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4903
4904         fragstring_length = 0;
4905         for (i = 0;i < fragstrings_count;i++)
4906                 fragstring_length += strlen(fragstrings_list[i]);
4907         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4908         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4909                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4910
4911         // try to load the cached shader, or generate one
4912         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4913
4914         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4915                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4916         else
4917                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4918
4919         // free the strings
4920         if (vertstring)
4921                 Mem_Free(vertstring);
4922         if (geomstring)
4923                 Mem_Free(geomstring);
4924         if (fragstring)
4925                 Mem_Free(fragstring);
4926         if (vertexstring)
4927                 Mem_Free(vertexstring);
4928         if (geometrystring)
4929                 Mem_Free(geometrystring);
4930         if (fragmentstring)
4931                 Mem_Free(fragmentstring);
4932 }
4933
4934 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4935 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4936 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4937 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4938 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4939 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4940
4941 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4942 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4943 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4944 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4945 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4946 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4947
4948 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4949 {
4950         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4951         if (r_hlsl_permutation != perm)
4952         {
4953                 r_hlsl_permutation = perm;
4954                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4955                 {
4956                         if (!r_hlsl_permutation->compiled)
4957                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4958                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4959                         {
4960                                 // remove features until we find a valid permutation
4961                                 int i;
4962                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4963                                 {
4964                                         // reduce i more quickly whenever it would not remove any bits
4965                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4966                                         if (!(permutation & j))
4967                                                 continue;
4968                                         permutation -= j;
4969                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4970                                         if (!r_hlsl_permutation->compiled)
4971                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4972                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4973                                                 break;
4974                                 }
4975                                 if (i >= SHADERPERMUTATION_COUNT)
4976                                 {
4977                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4978                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4979                                         return; // no bit left to clear, entire mode is broken
4980                                 }
4981                         }
4982                 }
4983                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4984                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4985         }
4986         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4987         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4988         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4989 }
4990 #endif
4991
4992 void R_GLSL_Restart_f(void)
4993 {
4994         unsigned int i, limit;
4995         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4996                 Mem_Free(glslshaderstring);
4997         glslshaderstring = NULL;
4998         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4999                 Mem_Free(cgshaderstring);
5000         cgshaderstring = NULL;
5001         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5002                 Mem_Free(hlslshaderstring);
5003         hlslshaderstring = NULL;
5004         switch(vid.renderpath)
5005         {
5006         case RENDERPATH_D3D9:
5007 #ifdef SUPPORTD3D
5008                 {
5009                         r_hlsl_permutation_t *p;
5010                         r_hlsl_permutation = NULL;
5011 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5016                         for (i = 0;i < limit;i++)
5017                         {
5018                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5019                                 {
5020                                         if (p->vertexshader)
5021                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5022                                         if (p->pixelshader)
5023                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5024                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5025                                 }
5026                         }
5027                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5028                 }
5029 #endif
5030                 break;
5031         case RENDERPATH_D3D10:
5032                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5033                 break;
5034         case RENDERPATH_D3D11:
5035                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5036                 break;
5037         case RENDERPATH_GL20:
5038                 {
5039                         r_glsl_permutation_t *p;
5040                         r_glsl_permutation = NULL;
5041                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5042                         for (i = 0;i < limit;i++)
5043                         {
5044                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5045                                 {
5046                                         GL_Backend_FreeProgram(p->program);
5047                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5048                                 }
5049                         }
5050                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5051                 }
5052                 break;
5053         case RENDERPATH_CGGL:
5054 #ifdef SUPPORTCG
5055                 {
5056                         r_cg_permutation_t *p;
5057                         r_cg_permutation = NULL;
5058                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5059                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5060                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5061                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5062                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5063                         for (i = 0;i < limit;i++)
5064                         {
5065                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5066                                 {
5067                                         if (p->vprogram)
5068                                                 cgDestroyProgram(p->vprogram);
5069                                         if (p->fprogram)
5070                                                 cgDestroyProgram(p->fprogram);
5071                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5072                                 }
5073                         }
5074                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5075                 }
5076 #endif
5077                 break;
5078         case RENDERPATH_GL13:
5079         case RENDERPATH_GL11:
5080                 break;
5081         }
5082 }
5083
5084 void R_GLSL_DumpShader_f(void)
5085 {
5086         int i;
5087         qfile_t *file;
5088
5089         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5090         if (file)
5091         {
5092                 FS_Print(file, "/* The engine may define the following macros:\n");
5093                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5094                 for (i = 0;i < SHADERMODE_COUNT;i++)
5095                         FS_Print(file, glslshadermodeinfo[i].pretext);
5096                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5097                         FS_Print(file, shaderpermutationinfo[i].pretext);
5098                 FS_Print(file, "*/\n");
5099                 FS_Print(file, builtinshaderstring);
5100                 FS_Close(file);
5101                 Con_Printf("glsl/default.glsl written\n");
5102         }
5103         else
5104                 Con_Printf("failed to write to glsl/default.glsl\n");
5105
5106 #ifdef SUPPORTCG
5107         file = FS_OpenRealFile("cg/default.cg", "w", false);
5108         if (file)
5109         {
5110                 FS_Print(file, "/* The engine may define the following macros:\n");
5111                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5112                 for (i = 0;i < SHADERMODE_COUNT;i++)
5113                         FS_Print(file, cgshadermodeinfo[i].pretext);
5114                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5115                         FS_Print(file, shaderpermutationinfo[i].pretext);
5116                 FS_Print(file, "*/\n");
5117                 FS_Print(file, builtincgshaderstring);
5118                 FS_Close(file);
5119                 Con_Printf("cg/default.cg written\n");
5120         }
5121         else
5122                 Con_Printf("failed to write to cg/default.cg\n");
5123 #endif
5124
5125 #ifdef SUPPORTD3D
5126         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5127         if (file)
5128         {
5129                 FS_Print(file, "/* The engine may define the following macros:\n");
5130                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5131                 for (i = 0;i < SHADERMODE_COUNT;i++)
5132                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5133                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5134                         FS_Print(file, shaderpermutationinfo[i].pretext);
5135                 FS_Print(file, "*/\n");
5136                 FS_Print(file, builtincgshaderstring);
5137                 FS_Close(file);
5138                 Con_Printf("hlsl/default.hlsl written\n");
5139         }
5140         else
5141                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5142 #endif
5143 }
5144
5145 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5146 {
5147         if (!second)
5148                 texturemode = GL_MODULATE;
5149         switch (vid.renderpath)
5150         {
5151         case RENDERPATH_D3D9:
5152 #ifdef SUPPORTD3D
5153                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5154                 R_Mesh_TexBind(GL20TU_FIRST , first );
5155                 R_Mesh_TexBind(GL20TU_SECOND, second);
5156 #endif
5157                 break;
5158         case RENDERPATH_D3D10:
5159                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5160                 break;
5161         case RENDERPATH_D3D11:
5162                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5163                 break;
5164         case RENDERPATH_GL20:
5165                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5166                 R_Mesh_TexBind(GL20TU_FIRST , first );
5167                 R_Mesh_TexBind(GL20TU_SECOND, second);
5168                 break;
5169         case RENDERPATH_CGGL:
5170 #ifdef SUPPORTCG
5171                 CHECKCGERROR
5172                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5173                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5174                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5175 #endif
5176                 break;
5177         case RENDERPATH_GL13:
5178                 R_Mesh_TexBind(0, first );
5179                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5180                 R_Mesh_TexBind(1, second);
5181                 if (second)
5182                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5183                 break;
5184         case RENDERPATH_GL11:
5185                 R_Mesh_TexBind(0, first );
5186                 break;
5187         }
5188 }
5189
5190 void R_SetupShader_DepthOrShadow(void)
5191 {
5192         switch (vid.renderpath)
5193         {
5194         case RENDERPATH_D3D9:
5195 #ifdef SUPPORTD3D
5196                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5197 #endif
5198                 break;
5199         case RENDERPATH_D3D10:
5200                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5201                 break;
5202         case RENDERPATH_D3D11:
5203                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5204                 break;
5205         case RENDERPATH_GL20:
5206                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5207                 break;
5208         case RENDERPATH_CGGL:
5209 #ifdef SUPPORTCG
5210                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5211 #endif
5212                 break;
5213         case RENDERPATH_GL13:
5214                 R_Mesh_TexBind(0, 0);
5215                 R_Mesh_TexBind(1, 0);
5216                 break;
5217         case RENDERPATH_GL11:
5218                 R_Mesh_TexBind(0, 0);
5219                 break;
5220         }
5221 }
5222
5223 void R_SetupShader_ShowDepth(void)
5224 {
5225         switch (vid.renderpath)
5226         {
5227         case RENDERPATH_D3D9:
5228 #ifdef SUPPORTHLSL
5229                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5230 #endif
5231                 break;
5232         case RENDERPATH_D3D10:
5233                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5234                 break;
5235         case RENDERPATH_D3D11:
5236                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5237                 break;
5238         case RENDERPATH_GL20:
5239                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5240                 break;
5241         case RENDERPATH_CGGL:
5242 #ifdef SUPPORTCG
5243                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5244 #endif
5245                 break;
5246         case RENDERPATH_GL13:
5247                 break;
5248         case RENDERPATH_GL11:
5249                 break;
5250         }
5251 }
5252
5253 extern qboolean r_shadow_usingdeferredprepass;
5254 extern cvar_t r_shadow_deferred_8bitrange;
5255 extern rtexture_t *r_shadow_attenuationgradienttexture;
5256 extern rtexture_t *r_shadow_attenuation2dtexture;
5257 extern rtexture_t *r_shadow_attenuation3dtexture;
5258 extern qboolean r_shadow_usingshadowmap2d;
5259 extern qboolean r_shadow_usingshadowmaportho;
5260 extern float r_shadow_shadowmap_texturescale[2];
5261 extern float r_shadow_shadowmap_parameters[4];
5262 extern qboolean r_shadow_shadowmapvsdct;
5263 extern qboolean r_shadow_shadowmapsampler;
5264 extern int r_shadow_shadowmappcf;
5265 extern rtexture_t *r_shadow_shadowmap2dtexture;
5266 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5267 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5268 extern matrix4x4_t r_shadow_shadowmapmatrix;
5269 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5270 extern int r_shadow_prepass_width;
5271 extern int r_shadow_prepass_height;
5272 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5273 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5274 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5275 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5276 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5277 extern cvar_t gl_mesh_separatearrays;
5278 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5279 {
5280         // a blendfunc allows colormod if:
5281         // a) it can never keep the destination pixel invariant, or
5282         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5283         // this is to prevent unintended side effects from colormod
5284
5285         // in formulas:
5286         // IF there is a (s, sa) for which for all (d, da),
5287         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5288         // THEN, for this (s, sa) and all (colormod, d, da):
5289         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5290         // OBVIOUSLY, this means that
5291         //   s*colormod * src(s*colormod, d, sa, da) = 0
5292         //   dst(s*colormod, d, sa, da)              = 1
5293
5294         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5295
5296         // main condition to leave dst color invariant:
5297         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5298         //   src == GL_ZERO:
5299         //     s * 0 + d * dst(s, d, sa, da) == d
5300         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301         //       => colormod is a problem for GL_SRC_COLOR only
5302         //   src == GL_ONE:
5303         //     s + d * dst(s, d, sa, da) == d
5304         //       => s == 0
5305         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306         //       => colormod is never problematic for these
5307         //   src == GL_SRC_COLOR:
5308         //     s*s + d * dst(s, d, sa, da) == d
5309         //       => s == 0
5310         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod is never problematic for these
5312         //   src == GL_ONE_MINUS_SRC_COLOR:
5313         //     s*(1-s) + d * dst(s, d, sa, da) == d
5314         //       => s == 0 or s == 1
5315         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is a problem for GL_SRC_COLOR only
5317         //   src == GL_DST_COLOR
5318         //     s*d + d * dst(s, d, sa, da) == d
5319         //       => s == 1
5320         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5321         //       => colormod is always a problem
5322         //     or
5323         //       => s == 0
5324         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5325         //       => colormod is never problematic for these
5326         //       => BUT, we do not know s! We must assume it is problematic
5327         //       then... except in GL_ONE case, where we know all invariant
5328         //       cases are fine
5329         //   src == GL_ONE_MINUS_DST_COLOR
5330         //     s*(1-d) + d * dst(s, d, sa, da) == d
5331         //       => s == 0 (1-d is impossible to handle for our desired result)
5332         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333         //       => colormod is never problematic for these
5334         //   src == GL_SRC_ALPHA
5335         //     s*sa + d * dst(s, d, sa, da) == d
5336         //       => s == 0, or sa == 0
5337         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338         //       => colormod breaks in the case GL_SRC_COLOR only
5339         //   src == GL_ONE_MINUS_SRC_ALPHA
5340         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5341         //       => s == 0, or sa == 1
5342         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5343         //       => colormod breaks in the case GL_SRC_COLOR only
5344         //   src == GL_DST_ALPHA
5345         //     s*da + d * dst(s, d, sa, da) == d
5346         //       => s == 0
5347         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5348         //       => colormod is never problematic for these
5349
5350         switch(src)
5351         {
5352                 case GL_ZERO:
5353                 case GL_ONE_MINUS_SRC_COLOR:
5354                 case GL_SRC_ALPHA:
5355                 case GL_ONE_MINUS_SRC_ALPHA:
5356                         if(dst == GL_SRC_COLOR)
5357                                 return false;
5358                         return true;
5359                 case GL_ONE:
5360                 case GL_SRC_COLOR:
5361                 case GL_ONE_MINUS_DST_COLOR:
5362                 case GL_DST_ALPHA:
5363                 case GL_ONE_MINUS_DST_ALPHA:
5364                         return true;
5365                 case GL_DST_COLOR:
5366                         if(dst == GL_ONE)
5367                                 return true;
5368                         return false;
5369                 default:
5370                         return false;
5371         }
5372 }
5373 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5374 {
5375         // select a permutation of the lighting shader appropriate to this
5376         // combination of texture, entity, light source, and fogging, only use the
5377         // minimum features necessary to avoid wasting rendering time in the
5378         // fragment shader on features that are not being used
5379         unsigned int permutation = 0;
5380         unsigned int mode = 0;
5381         qboolean allow_colormod;
5382         static float dummy_colormod[3] = {1, 1, 1};
5383         float *colormod = rsurface.colormod;
5384         float m16f[16];
5385         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5386         if (rsurfacepass == RSURFPASS_BACKGROUND)
5387         {
5388                 // distorted background
5389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5390                 {
5391                         mode = SHADERMODE_WATER;
5392                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5393                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5394                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5395                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5396                 }
5397                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5398                 {
5399                         mode = SHADERMODE_REFRACTION;
5400                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5401                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5402                 }
5403                 else
5404                 {
5405                         mode = SHADERMODE_GENERIC;
5406                         permutation |= SHADERPERMUTATION_DIFFUSE;
5407                         GL_BlendFunc(GL_ONE, GL_ZERO);
5408                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5409                 }
5410                 GL_AlphaTest(false);
5411         }
5412         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5413         {
5414                 if (r_glsl_offsetmapping.integer)
5415                 {
5416                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5417                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5418                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5419                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5420                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5421                         {
5422                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5423                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5424                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5425                         }
5426                 }
5427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5430                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5431                 // normalmap (deferred prepass), may use alpha test on diffuse
5432                 mode = SHADERMODE_DEFERREDGEOMETRY;
5433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435                 GL_AlphaTest(false);
5436                 GL_BlendFunc(GL_ONE, GL_ZERO);
5437                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5438         }
5439         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5440         {
5441                 if (r_glsl_offsetmapping.integer)
5442                 {
5443                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5444                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5445                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5446                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5447                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5448                         {
5449                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5450                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5451                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5452                         }
5453                 }
5454                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5455                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5456                 // light source
5457                 mode = SHADERMODE_LIGHTSOURCE;
5458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5459                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5460                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5461                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5462                 if (diffusescale > 0)
5463                         permutation |= SHADERPERMUTATION_DIFFUSE;
5464                 if (specularscale > 0)
5465                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5466                 if (r_refdef.fogenabled)
5467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5468                 if (rsurface.texture->colormapping)
5469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5470                 if (r_shadow_usingshadowmap2d)
5471                 {
5472                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5473                         if(r_shadow_shadowmapvsdct)
5474                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5475
5476                         if (r_shadow_shadowmapsampler)
5477                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5478                         if (r_shadow_shadowmappcf > 1)
5479                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5480                         else if (r_shadow_shadowmappcf)
5481                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5482                 }
5483                 if (rsurface.texture->reflectmasktexture)
5484                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5485                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5486                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5487                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5488         }
5489         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5490         {
5491                 if (r_glsl_offsetmapping.integer)
5492                 {
5493                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5494                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5495                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5496                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5497                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5498                         {
5499                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5500                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5501                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5502                         }
5503                 }
5504                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5505                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5506                 // unshaded geometry (fullbright or ambient model lighting)
5507                 mode = SHADERMODE_FLATCOLOR;
5508                 ambientscale = diffusescale = specularscale = 0;
5509                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5510                         permutation |= SHADERPERMUTATION_GLOW;
5511                 if (r_refdef.fogenabled)
5512                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5513                 if (rsurface.texture->colormapping)
5514                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5515                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5516                 {
5517                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5518                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5519
5520                         if (r_shadow_shadowmapsampler)
5521                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5522                         if (r_shadow_shadowmappcf > 1)
5523                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5524                         else if (r_shadow_shadowmappcf)
5525                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5526                 }
5527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5528                         permutation |= SHADERPERMUTATION_REFLECTION;
5529                 if (rsurface.texture->reflectmasktexture)
5530                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5531                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5532                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5533                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5534         }
5535         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5536         {
5537                 if (r_glsl_offsetmapping.integer)
5538                 {
5539                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5540                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5541                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5542                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5543                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5544                         {
5545                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5546                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5547                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5548                         }
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5551                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5552                 // directional model lighting
5553                 mode = SHADERMODE_LIGHTDIRECTION;
5554                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5555                         permutation |= SHADERPERMUTATION_GLOW;
5556                 permutation |= SHADERPERMUTATION_DIFFUSE;
5557                 if (specularscale > 0)
5558                         permutation |= SHADERPERMUTATION_SPECULAR;
5559                 if (r_refdef.fogenabled)
5560                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5561                 if (rsurface.texture->colormapping)
5562                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5563                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5564                 {
5565                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5566                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5567
5568                         if (r_shadow_shadowmapsampler)
5569                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5570                         if (r_shadow_shadowmappcf > 1)
5571                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5572                         else if (r_shadow_shadowmappcf)
5573                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5574                 }
5575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5576                         permutation |= SHADERPERMUTATION_REFLECTION;
5577                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5578                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5579                 if (rsurface.texture->reflectmasktexture)
5580                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5581                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5582                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5583                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5584         }
5585         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5586         {
5587                 if (r_glsl_offsetmapping.integer)
5588                 {
5589                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5590                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5591                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5592                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5593                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5594                         {
5595                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5596                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5597                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5598                         }
5599                 }
5600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5601                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5602                 // ambient model lighting
5603                 mode = SHADERMODE_LIGHTDIRECTION;
5604                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5605                         permutation |= SHADERPERMUTATION_GLOW;
5606                 if (r_refdef.fogenabled)
5607                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5608                 if (rsurface.texture->colormapping)
5609                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5610                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5611                 {
5612                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5613                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5614
5615                         if (r_shadow_shadowmapsampler)
5616                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5617                         if (r_shadow_shadowmappcf > 1)
5618                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5619                         else if (r_shadow_shadowmappcf)
5620                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5621                 }
5622                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5623                         permutation |= SHADERPERMUTATION_REFLECTION;
5624                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5625                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5626                 if (rsurface.texture->reflectmasktexture)
5627                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5628                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5629                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5630                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5631         }
5632         else
5633         {
5634                 if (r_glsl_offsetmapping.integer)
5635                 {
5636                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5638                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5639                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5640                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5641                         {
5642                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5643                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5644                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5645                         }
5646                 }
5647                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5648                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5649                 // lightmapped wall
5650                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5651                         permutation |= SHADERPERMUTATION_GLOW;
5652                 if (r_refdef.fogenabled)
5653                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5654                 if (rsurface.texture->colormapping)
5655                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5656                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5657                 {
5658                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5659                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5660
5661                         if (r_shadow_shadowmapsampler)
5662                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5663                         if (r_shadow_shadowmappcf > 1)
5664                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5665                         else if (r_shadow_shadowmappcf)
5666                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5667                 }
5668                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5669                         permutation |= SHADERPERMUTATION_REFLECTION;
5670                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5671                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5672                 if (rsurface.texture->reflectmasktexture)
5673                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5674                 if (FAKELIGHT_ENABLED)
5675                 {
5676                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5677                         mode = SHADERMODE_FAKELIGHT;
5678                         permutation |= SHADERPERMUTATION_DIFFUSE;
5679                         if (specularscale > 0)
5680                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5681                 }
5682                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5683                 {
5684                         // deluxemapping (light direction texture)
5685                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5686                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5687                         else
5688                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5689                         permutation |= SHADERPERMUTATION_DIFFUSE;
5690                         if (specularscale > 0)
5691                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5692                 }
5693                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5694                 {
5695                         // fake deluxemapping (uniform light direction in tangentspace)
5696                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5697                         permutation |= SHADERPERMUTATION_DIFFUSE;
5698                         if (specularscale > 0)
5699                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5700                 }
5701                 else if (rsurface.uselightmaptexture)
5702                 {
5703                         // ordinary lightmapping (q1bsp, q3bsp)
5704                         mode = SHADERMODE_LIGHTMAP;
5705                 }
5706                 else
5707                 {
5708                         // ordinary vertex coloring (q3bsp)
5709                         mode = SHADERMODE_VERTEXCOLOR;
5710                 }
5711                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5712                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5713                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5714         }
5715         if(!allow_colormod)
5716                 colormod = dummy_colormod;
5717         switch(vid.renderpath)
5718         {
5719         case RENDERPATH_D3D9:
5720 #ifdef SUPPORTD3D
5721                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5722                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5723                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5724                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5725                 if (mode == SHADERMODE_LIGHTSOURCE)
5726                 {
5727                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5728                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5729                 }
5730                 else
5731                 {
5732                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5733                         {
5734                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5735                         }
5736                 }
5737                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5738                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5739                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5740                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5741                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5742
5743                 if (mode == SHADERMODE_LIGHTSOURCE)
5744                 {
5745                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5746                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5747                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5749                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5750
5751                         // additive passes are only darkened by fog, not tinted
5752                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5753                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5754                 }
5755                 else
5756                 {
5757                         if (mode == SHADERMODE_FLATCOLOR)
5758                         {
5759                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5760                         }
5761                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5762                         {
5763                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5766                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5767                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5770                         }
5771                         else
5772                         {
5773                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5776                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5777                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5778                         }
5779                         // additive passes are only darkened by fog, not tinted
5780                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5781                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5782                         else
5783                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5784                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5785                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5786                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5788                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5790                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5791                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5792                         if (mode == SHADERMODE_WATER)
5793                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5794                 }
5795                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5796                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5797                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5798                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5799                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5800                 if (rsurface.texture->pantstexture)
5801                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5802                 else
5803                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5804                 if (rsurface.texture->shirttexture)
5805                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5806                 else
5807                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5808                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5809                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5810                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5812                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5813                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5814                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5815
5816                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5817                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5818                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5819                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5825                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5827                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5828                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5829                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5830                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5831                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5832                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5833                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5834                 {
5835                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5836                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5837                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5838                 }
5839                 else
5840                 {
5841                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5842                 }
5843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5844 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5846                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5847                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5848                 {
5849                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5850                         if (rsurface.rtlight)
5851                         {
5852                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5853                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5854                         }
5855                 }
5856 #endif
5857                 break;
5858         case RENDERPATH_D3D10:
5859                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5860                 break;
5861         case RENDERPATH_D3D11:
5862                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5863                 break;
5864         case RENDERPATH_GL20:
5865                 if (gl_mesh_separatearrays.integer)
5866                 {
5867                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5868                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5869                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5870                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5871                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5872                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5874                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5875                 }
5876                 else
5877                 {
5878                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5879                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5880                 }
5881                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5882                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5883                 if (mode == SHADERMODE_LIGHTSOURCE)
5884                 {
5885                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5886                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5887                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5888                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5889                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5890                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5891         
5892                         // additive passes are only darkened by fog, not tinted
5893                         if (r_glsl_permutation->loc_FogColor >= 0)
5894                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5895                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5896                 }
5897                 else
5898                 {
5899                         if (mode == SHADERMODE_FLATCOLOR)
5900                         {
5901                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5902                         }
5903                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5904                         {
5905                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5906                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5907                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5908                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5909                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5910                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5911                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5912                         }
5913                         else
5914                         {
5915                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5916                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5917                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5918                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5919                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5920                         }
5921                         // additive passes are only darkened by fog, not tinted
5922                         if (r_glsl_permutation->loc_FogColor >= 0)
5923                         {
5924                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5925                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5926                                 else
5927                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5928                         }
5929                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5930                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5931                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5932                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5933                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5934                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5935                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5936                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5937                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5938                 }
5939                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5940                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5941                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5942                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5943                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5944
5945                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5946                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5947                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5948                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5949                 {
5950                         if (rsurface.texture->pantstexture)
5951                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5952                         else
5953                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5954                 }
5955                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5956                 {
5957                         if (rsurface.texture->shirttexture)
5958                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5959                         else
5960                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5961                 }
5962                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5963                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5964                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5965                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5966                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5967                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5969
5970         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5971         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5972         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5973                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5974                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5975                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5976                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5977                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5978                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5979                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5980                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5981                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5982                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5983                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5984                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5985                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5986                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5987                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5988                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5989                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5990                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5991                 {
5992                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5993                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5994                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5995                 }
5996                 else
5997                 {
5998                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5999                 }
6000 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6001 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6002                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6003                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6004                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6005                 {
6006                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6007                         if (rsurface.rtlight)
6008                         {
6009                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6010                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6011                         }
6012                 }
6013                 CHECKGLERROR
6014                 break;
6015         case RENDERPATH_CGGL:
6016 #ifdef SUPPORTCG
6017                 if (gl_mesh_separatearrays.integer)
6018                 {
6019                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6020                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6021                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6022                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6023                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6024                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6026                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6027                 }
6028                 else
6029                 {
6030                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6031                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6032                 }
6033                 R_SetupShader_SetPermutationCG(mode, permutation);
6034                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6035                 if (mode == SHADERMODE_LIGHTSOURCE)
6036                 {
6037                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6038                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6039                 }
6040                 else
6041                 {
6042                         if (mode == SHADERMODE_LIGHTDIRECTION)
6043                         {
6044                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6045                         }
6046                 }
6047                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6048                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6049                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6050                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6051                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6052                 CHECKGLERROR
6053
6054                 if (mode == SHADERMODE_LIGHTSOURCE)
6055                 {
6056                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6057                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6058                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6059                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6060                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
6061
6062                         // additive passes are only darkened by fog, not tinted
6063                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6064                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6065                 }
6066                 else
6067                 {
6068                         if (mode == SHADERMODE_FLATCOLOR)
6069                         {
6070                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6071                         }
6072                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6073                         {
6074                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6075                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6076                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6077                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6078                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6079                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
6080                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6081                         }
6082                         else
6083                         {
6084                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6085                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
6086                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6087                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6088                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6089                         }
6090                         // additive passes are only darkened by fog, not tinted
6091                         if (r_cg_permutation->fp_FogColor)
6092                         {
6093                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6094                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6095                                 else
6096                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6097                                 CHECKCGERROR
6098                         }
6099                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
6100                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
6101                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
6102                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6103                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6104                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6105                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6106                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6107                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6108                 }
6109                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6110                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6111                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6112                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6113                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6114                 if (r_cg_permutation->fp_Color_Pants)
6115                 {
6116                         if (rsurface.texture->pantstexture)
6117                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6118                         else
6119                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6120                         CHECKCGERROR
6121                 }
6122                 if (r_cg_permutation->fp_Color_Shirt)
6123                 {
6124                         if (rsurface.texture->shirttexture)
6125                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6126                         else
6127                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6128                         CHECKCGERROR
6129                 }
6130                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6131                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6132                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6133                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6134                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6135                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6136                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6137
6138         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6139         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6140         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6152                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
6153                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6158                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6159                 {
6160                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6161                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6162                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6163                 }
6164                 else
6165                 {
6166                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6167                 }
6168                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6169                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6170                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6171                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6172                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6173                 {
6174                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6175                         if (rsurface.rtlight)
6176                         {
6177                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6178                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6179                         }
6180                 }
6181
6182                 CHECKGLERROR
6183 #endif
6184                 break;
6185         case RENDERPATH_GL13:
6186         case RENDERPATH_GL11:
6187                 break;
6188         }
6189 }
6190
6191 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6192 {
6193         // select a permutation of the lighting shader appropriate to this
6194         // combination of texture, entity, light source, and fogging, only use the
6195         // minimum features necessary to avoid wasting rendering time in the
6196         // fragment shader on features that are not being used
6197         unsigned int permutation = 0;
6198         unsigned int mode = 0;
6199         const float *lightcolorbase = rtlight->currentcolor;
6200         float ambientscale = rtlight->ambientscale;
6201         float diffusescale = rtlight->diffusescale;
6202         float specularscale = rtlight->specularscale;
6203         // this is the location of the light in view space
6204         vec3_t viewlightorigin;
6205         // this transforms from view space (camera) to light space (cubemap)
6206         matrix4x4_t viewtolight;
6207         matrix4x4_t lighttoview;
6208         float viewtolight16f[16];
6209         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6210         // light source
6211         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6212         if (rtlight->currentcubemap != r_texture_whitecube)
6213                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6214         if (diffusescale > 0)
6215                 permutation |= SHADERPERMUTATION_DIFFUSE;
6216         if (specularscale > 0)
6217                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6218         if (r_shadow_usingshadowmap2d)
6219         {
6220                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6221                 if (r_shadow_shadowmapvsdct)
6222                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6223
6224                 if (r_shadow_shadowmapsampler)
6225                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6226                 if (r_shadow_shadowmappcf > 1)
6227                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6228                 else if (r_shadow_shadowmappcf)
6229                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6230         }
6231         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6232         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6233         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6234         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6235         switch(vid.renderpath)
6236         {
6237         case RENDERPATH_D3D9:
6238 #ifdef SUPPORTD3D
6239                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6240                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6241                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6242                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6243                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6244                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6245                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6246                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6247                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6248                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6250
6251                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6252                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6253                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6254                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6255                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6256                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6257 #endif
6258                 break;
6259         case RENDERPATH_D3D10:
6260                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6261                 break;
6262         case RENDERPATH_D3D11:
6263                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6264                 break;
6265         case RENDERPATH_GL20:
6266                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6267                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6268                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6269                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6270                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6271                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6272                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6273                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6274                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6275                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6276                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6277
6278                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6279                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6280                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6281                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6282                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6283                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6284                 break;
6285         case RENDERPATH_CGGL:
6286 #ifdef SUPPORTCG
6287                 R_SetupShader_SetPermutationCG(mode, permutation);
6288                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6289                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6290                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
6291                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
6292                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6293                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6294                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6295                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6296                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6297                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6298
6299                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6300                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6301                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6302                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6303                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6304                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6305 #endif
6306                 break;
6307         case RENDERPATH_GL13:
6308         case RENDERPATH_GL11:
6309                 break;
6310         }
6311 }
6312
6313 #define SKINFRAME_HASH 1024
6314
6315 typedef struct
6316 {
6317         int loadsequence; // incremented each level change
6318         memexpandablearray_t array;
6319         skinframe_t *hash[SKINFRAME_HASH];
6320 }
6321 r_skinframe_t;
6322 r_skinframe_t r_skinframe;
6323
6324 void R_SkinFrame_PrepareForPurge(void)
6325 {
6326         r_skinframe.loadsequence++;
6327         // wrap it without hitting zero
6328         if (r_skinframe.loadsequence >= 200)
6329                 r_skinframe.loadsequence = 1;
6330 }
6331
6332 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6333 {
6334         if (!skinframe)
6335                 return;
6336         // mark the skinframe as used for the purging code
6337         skinframe->loadsequence = r_skinframe.loadsequence;
6338 }
6339
6340 void R_SkinFrame_Purge(void)
6341 {
6342         int i;
6343         skinframe_t *s;
6344         for (i = 0;i < SKINFRAME_HASH;i++)
6345         {
6346                 for (s = r_skinframe.hash[i];s;s = s->next)
6347                 {
6348                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6349                         {
6350                                 if (s->merged == s->base)
6351                                         s->merged = NULL;
6352                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6353                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6354                                 R_PurgeTexture(s->merged);s->merged = NULL;
6355                                 R_PurgeTexture(s->base  );s->base   = NULL;
6356                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6357                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6358                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6359                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6360                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6361                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6362                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6363                                 s->loadsequence = 0;
6364                         }
6365                 }
6366         }
6367 }
6368
6369 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6370         skinframe_t *item;
6371         char basename[MAX_QPATH];
6372
6373         Image_StripImageExtension(name, basename, sizeof(basename));
6374
6375         if( last == NULL ) {
6376                 int hashindex;
6377                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6378                 item = r_skinframe.hash[hashindex];
6379         } else {
6380                 item = last->next;
6381         }
6382
6383         // linearly search through the hash bucket
6384         for( ; item ; item = item->next ) {
6385                 if( !strcmp( item->basename, basename ) ) {
6386                         return item;
6387                 }
6388         }
6389         return NULL;
6390 }
6391
6392 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6393 {
6394         skinframe_t *item;
6395         int hashindex;
6396         char basename[MAX_QPATH];
6397
6398         Image_StripImageExtension(name, basename, sizeof(basename));
6399
6400         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6401         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6402                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6403                         break;
6404
6405         if (!item) {
6406                 rtexture_t *dyntexture;
6407                 // check whether its a dynamic texture
6408                 dyntexture = CL_GetDynTexture( basename );
6409                 if (!add && !dyntexture)
6410                         return NULL;
6411                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6412                 memset(item, 0, sizeof(*item));
6413                 strlcpy(item->basename, basename, sizeof(item->basename));
6414                 item->base = dyntexture; // either NULL or dyntexture handle
6415                 item->textureflags = textureflags;
6416                 item->comparewidth = comparewidth;
6417                 item->compareheight = compareheight;
6418                 item->comparecrc = comparecrc;
6419                 item->next = r_skinframe.hash[hashindex];
6420                 r_skinframe.hash[hashindex] = item;
6421         }
6422         else if( item->base == NULL )
6423         {
6424                 rtexture_t *dyntexture;
6425                 // check whether its a dynamic texture
6426                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
6427                 dyntexture = CL_GetDynTexture( basename );
6428                 item->base = dyntexture; // either NULL or dyntexture handle
6429         }
6430
6431         R_SkinFrame_MarkUsed(item);
6432         return item;
6433 }
6434
6435 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6436         { \
6437                 unsigned long long avgcolor[5], wsum; \
6438                 int pix, comp, w; \
6439                 avgcolor[0] = 0; \
6440                 avgcolor[1] = 0; \
6441                 avgcolor[2] = 0; \
6442                 avgcolor[3] = 0; \
6443                 avgcolor[4] = 0; \
6444                 wsum = 0; \
6445                 for(pix = 0; pix < cnt; ++pix) \
6446                 { \
6447                         w = 0; \
6448                         for(comp = 0; comp < 3; ++comp) \
6449                                 w += getpixel; \
6450                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6451                         { \
6452                                 ++wsum; \
6453                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6454                                 w = getpixel; \
6455                                 for(comp = 0; comp < 3; ++comp) \
6456                                         avgcolor[comp] += getpixel * w; \
6457                                 avgcolor[3] += w; \
6458                         } \
6459                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6460                         avgcolor[4] += getpixel; \
6461                 } \
6462                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6463                         avgcolor[3] = 1; \
6464                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6465                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6466                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6467                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6468         }
6469
6470 extern cvar_t gl_picmip;
6471 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6472 {
6473         int j;
6474         unsigned char *pixels;
6475         unsigned char *bumppixels;
6476         unsigned char *basepixels = NULL;
6477         int basepixels_width = 0;
6478         int basepixels_height = 0;
6479         skinframe_t *skinframe;
6480         rtexture_t *ddsbase = NULL;
6481         qboolean ddshasalpha = false;
6482         float ddsavgcolor[4];
6483         char basename[MAX_QPATH];
6484         int miplevel = R_PicmipForFlags(textureflags);
6485         int savemiplevel = miplevel;
6486         int mymiplevel;
6487
6488         if (cls.state == ca_dedicated)
6489                 return NULL;
6490
6491         // return an existing skinframe if already loaded
6492         // if loading of the first image fails, don't make a new skinframe as it
6493         // would cause all future lookups of this to be missing
6494         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6495         if (skinframe && skinframe->base)
6496                 return skinframe;
6497
6498         Image_StripImageExtension(name, basename, sizeof(basename));
6499
6500         // check for DDS texture file first
6501         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6502         {
6503                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6504                 if (basepixels == NULL)
6505                         return NULL;
6506         }
6507
6508         // FIXME handle miplevel
6509
6510         if (developer_loading.integer)
6511                 Con_Printf("loading skin \"%s\"\n", name);
6512
6513         // we've got some pixels to store, so really allocate this new texture now
6514         if (!skinframe)
6515                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6516         skinframe->stain = NULL;
6517         skinframe->merged = NULL;
6518         skinframe->base = NULL;
6519         skinframe->pants = NULL;
6520         skinframe->shirt = NULL;
6521         skinframe->nmap = NULL;
6522         skinframe->gloss = NULL;
6523         skinframe->glow = NULL;
6524         skinframe->fog = NULL;
6525         skinframe->reflect = NULL;
6526         skinframe->hasalpha = false;
6527
6528         if (ddsbase)
6529         {
6530                 skinframe->base = ddsbase;
6531                 skinframe->hasalpha = ddshasalpha;
6532                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6533                 if (r_loadfog && skinframe->hasalpha)
6534                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6535                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6536         }
6537         else
6538         {
6539                 basepixels_width = image_width;
6540                 basepixels_height = image_height;
6541                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6542                 if (textureflags & TEXF_ALPHA)
6543                 {
6544                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6545                         {
6546                                 if (basepixels[j] < 255)
6547                                 {
6548                                         skinframe->hasalpha = true;
6549                                         break;
6550                                 }
6551                         }
6552                         if (r_loadfog && skinframe->hasalpha)
6553                         {
6554                                 // has transparent pixels
6555                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6556                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6557                                 {
6558                                         pixels[j+0] = 255;
6559                                         pixels[j+1] = 255;
6560                                         pixels[j+2] = 255;
6561                                         pixels[j+3] = basepixels[j+3];
6562                                 }
6563                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6564                                 Mem_Free(pixels);
6565                         }
6566                 }
6567                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6568                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6569                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6570                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6572                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6573         }
6574
6575         if (r_loaddds)
6576         {
6577                 mymiplevel = savemiplevel;
6578                 if (r_loadnormalmap)
6579                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6580                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6581                 if (r_loadgloss)
6582                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6583                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6584                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6585                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6586         }
6587
6588         // _norm is the name used by tenebrae and has been adopted as standard
6589         if (r_loadnormalmap && skinframe->nmap == NULL)
6590         {
6591                 mymiplevel = savemiplevel;
6592                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6593                 {
6594                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6595                         Mem_Free(pixels);
6596                         pixels = NULL;
6597                 }
6598                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6599                 {
6600                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6601                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6602                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6603                         Mem_Free(pixels);
6604                         Mem_Free(bumppixels);
6605                 }
6606                 else if (r_shadow_bumpscale_basetexture.value > 0)
6607                 {
6608                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6609                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6610                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6611                         Mem_Free(pixels);
6612                 }
6613                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6614                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6615         }
6616
6617         // _luma is supported only for tenebrae compatibility
6618         // _glow is the preferred name
6619         mymiplevel = savemiplevel;
6620         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6621         {
6622                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6624                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6625                 Mem_Free(pixels);pixels = NULL;
6626         }
6627
6628         mymiplevel = savemiplevel;
6629         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6630         {
6631                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6632                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6633                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6634                 Mem_Free(pixels);
6635                 pixels = NULL;
6636         }
6637
6638         mymiplevel = savemiplevel;
6639         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6640         {
6641                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6642                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6643                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6644                 Mem_Free(pixels);
6645                 pixels = NULL;
6646         }
6647
6648         mymiplevel = savemiplevel;
6649         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6650         {
6651                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6652                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6653                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6654                 Mem_Free(pixels);
6655                 pixels = NULL;
6656         }
6657
6658         mymiplevel = savemiplevel;
6659         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6660         {
6661                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6662                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6663                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6664                 Mem_Free(pixels);
6665                 pixels = NULL;
6666         }
6667
6668         if (basepixels)
6669                 Mem_Free(basepixels);
6670
6671         return skinframe;
6672 }
6673
6674 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6675 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6676 {
6677         int i;
6678         unsigned char *temp1, *temp2;
6679         skinframe_t *skinframe;
6680
6681         if (cls.state == ca_dedicated)
6682                 return NULL;
6683
6684         // if already loaded just return it, otherwise make a new skinframe
6685         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6686         if (skinframe && skinframe->base)
6687                 return skinframe;
6688
6689         skinframe->stain = NULL;
6690         skinframe->merged = NULL;
6691         skinframe->base = NULL;
6692         skinframe->pants = NULL;
6693         skinframe->shirt = NULL;
6694         skinframe->nmap = NULL;
6695         skinframe->gloss = NULL;
6696         skinframe->glow = NULL;
6697         skinframe->fog = NULL;
6698         skinframe->reflect = NULL;
6699         skinframe->hasalpha = false;
6700
6701         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6702         if (!skindata)
6703                 return NULL;
6704
6705         if (developer_loading.integer)
6706                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6707
6708         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6709         {
6710                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6711                 temp2 = temp1 + width * height * 4;
6712                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6713                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6714                 Mem_Free(temp1);
6715         }
6716         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6717         if (textureflags & TEXF_ALPHA)
6718         {
6719                 for (i = 3;i < width * height * 4;i += 4)
6720                 {
6721                         if (skindata[i] < 255)
6722                         {
6723                                 skinframe->hasalpha = true;
6724                                 break;
6725                         }
6726                 }
6727                 if (r_loadfog && skinframe->hasalpha)
6728                 {
6729                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6730                         memcpy(fogpixels, skindata, width * height * 4);
6731                         for (i = 0;i < width * height * 4;i += 4)
6732                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6733                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6734                         Mem_Free(fogpixels);
6735                 }
6736         }
6737
6738         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6739         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6740
6741         return skinframe;
6742 }
6743
6744 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6745 {
6746         int i;
6747         int featuresmask;
6748         skinframe_t *skinframe;
6749
6750         if (cls.state == ca_dedicated)
6751                 return NULL;
6752
6753         // if already loaded just return it, otherwise make a new skinframe
6754         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6755         if (skinframe && skinframe->base)
6756                 return skinframe;
6757
6758         skinframe->stain = NULL;
6759         skinframe->merged = NULL;
6760         skinframe->base = NULL;
6761         skinframe->pants = NULL;
6762         skinframe->shirt = NULL;
6763         skinframe->nmap = NULL;
6764         skinframe->gloss = NULL;
6765         skinframe->glow = NULL;
6766         skinframe->fog = NULL;
6767         skinframe->reflect = NULL;
6768         skinframe->hasalpha = false;
6769
6770         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6771         if (!skindata)
6772                 return NULL;
6773
6774         if (developer_loading.integer)
6775                 Con_Printf("loading quake skin \"%s\"\n", name);
6776
6777         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6778         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6779         memcpy(skinframe->qpixels, skindata, width*height);
6780         skinframe->qwidth = width;
6781         skinframe->qheight = height;
6782
6783         featuresmask = 0;
6784         for (i = 0;i < width * height;i++)
6785                 featuresmask |= palette_featureflags[skindata[i]];
6786
6787         skinframe->hasalpha = false;
6788         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6789         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6790         skinframe->qgeneratemerged = true;
6791         skinframe->qgeneratebase = skinframe->qhascolormapping;
6792         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6793
6794         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6795         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6796
6797         return skinframe;
6798 }
6799
6800 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6801 {
6802         int width;
6803         int height;
6804         unsigned char *skindata;
6805
6806         if (!skinframe->qpixels)
6807                 return;
6808
6809         if (!skinframe->qhascolormapping)
6810                 colormapped = false;
6811
6812         if (colormapped)
6813         {
6814                 if (!skinframe->qgeneratebase)
6815                         return;
6816         }
6817         else
6818         {
6819                 if (!skinframe->qgeneratemerged)
6820                         return;
6821         }
6822
6823         width = skinframe->qwidth;
6824         height = skinframe->qheight;
6825         skindata = skinframe->qpixels;
6826
6827         if (skinframe->qgeneratenmap)
6828         {
6829                 unsigned char *temp1, *temp2;
6830                 skinframe->qgeneratenmap = false;
6831                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6832                 temp2 = temp1 + width * height * 4;
6833                 // use either a custom palette or the quake palette
6834                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6835                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6836                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6837                 Mem_Free(temp1);
6838         }
6839
6840         if (skinframe->qgenerateglow)
6841         {
6842                 skinframe->qgenerateglow = false;
6843                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6844         }
6845
6846         if (colormapped)
6847         {
6848                 skinframe->qgeneratebase = false;
6849                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6850                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6851                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6852         }
6853         else
6854         {
6855                 skinframe->qgeneratemerged = false;
6856                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6857         }
6858
6859         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6860         {
6861                 Mem_Free(skinframe->qpixels);
6862                 skinframe->qpixels = NULL;
6863         }
6864 }
6865
6866 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6867 {
6868         int i;
6869         skinframe_t *skinframe;
6870
6871         if (cls.state == ca_dedicated)
6872                 return NULL;
6873
6874         // if already loaded just return it, otherwise make a new skinframe
6875         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6876         if (skinframe && skinframe->base)
6877                 return skinframe;
6878
6879         skinframe->stain = NULL;
6880         skinframe->merged = NULL;
6881         skinframe->base = NULL;
6882         skinframe->pants = NULL;
6883         skinframe->shirt = NULL;
6884         skinframe->nmap = NULL;
6885         skinframe->gloss = NULL;
6886         skinframe->glow = NULL;
6887         skinframe->fog = NULL;
6888         skinframe->reflect = NULL;
6889         skinframe->hasalpha = false;
6890
6891         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6892         if (!skindata)
6893                 return NULL;
6894
6895         if (developer_loading.integer)
6896                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6897
6898         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6899         if (textureflags & TEXF_ALPHA)
6900         {
6901                 for (i = 0;i < width * height;i++)
6902                 {
6903                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6904                         {
6905                                 skinframe->hasalpha = true;
6906                                 break;
6907                         }
6908                 }
6909                 if (r_loadfog && skinframe->hasalpha)
6910                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6911         }
6912
6913         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6914         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6915
6916         return skinframe;
6917 }
6918
6919 skinframe_t *R_SkinFrame_LoadMissing(void)
6920 {
6921         skinframe_t *skinframe;
6922
6923         if (cls.state == ca_dedicated)
6924                 return NULL;
6925
6926         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6927         skinframe->stain = NULL;
6928         skinframe->merged = NULL;
6929         skinframe->base = NULL;
6930         skinframe->pants = NULL;
6931         skinframe->shirt = NULL;
6932         skinframe->nmap = NULL;
6933         skinframe->gloss = NULL;
6934         skinframe->glow = NULL;
6935         skinframe->fog = NULL;
6936         skinframe->reflect = NULL;
6937         skinframe->hasalpha = false;
6938
6939         skinframe->avgcolor[0] = rand() / RAND_MAX;
6940         skinframe->avgcolor[1] = rand() / RAND_MAX;
6941         skinframe->avgcolor[2] = rand() / RAND_MAX;
6942         skinframe->avgcolor[3] = 1;
6943
6944         return skinframe;
6945 }
6946
6947 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6948 typedef struct suffixinfo_s
6949 {
6950         const char *suffix;
6951         qboolean flipx, flipy, flipdiagonal;
6952 }
6953 suffixinfo_t;
6954 static suffixinfo_t suffix[3][6] =
6955 {
6956         {
6957                 {"px",   false, false, false},
6958                 {"nx",   false, false, false},
6959                 {"py",   false, false, false},
6960                 {"ny",   false, false, false},
6961                 {"pz",   false, false, false},
6962                 {"nz",   false, false, false}
6963         },
6964         {
6965                 {"posx", false, false, false},
6966                 {"negx", false, false, false},
6967                 {"posy", false, false, false},
6968                 {"negy", false, false, false},
6969                 {"posz", false, false, false},
6970                 {"negz", false, false, false}
6971         },
6972         {
6973                 {"rt",    true, false,  true},
6974                 {"lf",   false,  true,  true},
6975                 {"ft",    true,  true, false},
6976                 {"bk",   false, false, false},
6977                 {"up",    true, false,  true},
6978                 {"dn",    true, false,  true}
6979         }
6980 };
6981
6982 static int componentorder[4] = {0, 1, 2, 3};
6983
6984 rtexture_t *R_LoadCubemap(const char *basename)
6985 {
6986         int i, j, cubemapsize;
6987         unsigned char *cubemappixels, *image_buffer;
6988         rtexture_t *cubemaptexture;
6989         char name[256];
6990         // must start 0 so the first loadimagepixels has no requested width/height
6991         cubemapsize = 0;
6992         cubemappixels = NULL;
6993         cubemaptexture = NULL;
6994         // keep trying different suffix groups (posx, px, rt) until one loads
6995         for (j = 0;j < 3 && !cubemappixels;j++)
6996         {
6997                 // load the 6 images in the suffix group
6998                 for (i = 0;i < 6;i++)
6999                 {
7000                         // generate an image name based on the base and and suffix
7001                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7002                         // load it
7003                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7004                         {
7005                                 // an image loaded, make sure width and height are equal
7006                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7007                                 {
7008                                         // if this is the first image to load successfully, allocate the cubemap memory
7009                                         if (!cubemappixels && image_width >= 1)
7010                                         {
7011                                                 cubemapsize = image_width;
7012                                                 // note this clears to black, so unavailable sides are black
7013                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7014                                         }
7015                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7016                                         if (cubemappixels)
7017                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
7018                                 }
7019                                 else
7020                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7021                                 // free the image
7022                                 Mem_Free(image_buffer);
7023                         }
7024                 }
7025         }
7026         // if a cubemap loaded, upload it
7027         if (cubemappixels)
7028         {
7029                 if (developer_loading.integer)
7030                         Con_Printf("loading cubemap \"%s\"\n", basename);
7031
7032                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7033                 Mem_Free(cubemappixels);
7034         }
7035         else
7036         {
7037                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7038                 if (developer_loading.integer)
7039                 {
7040                         Con_Printf("(tried tried images ");
7041                         for (j = 0;j < 3;j++)
7042                                 for (i = 0;i < 6;i++)
7043                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7044                         Con_Print(" and was unable to find any of them).\n");
7045                 }
7046         }
7047         return cubemaptexture;
7048 }
7049
7050 rtexture_t *R_GetCubemap(const char *basename)
7051 {
7052         int i;
7053         for (i = 0;i < r_texture_numcubemaps;i++)
7054                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7055                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7056         if (i >= MAX_CUBEMAPS)
7057                 return r_texture_whitecube;
7058         r_texture_numcubemaps++;
7059         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7060         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7061         return r_texture_cubemaps[i].texture;
7062 }
7063
7064 void R_FreeCubemaps(void)
7065 {
7066         int i;
7067         for (i = 0;i < r_texture_numcubemaps;i++)
7068         {
7069                 if (developer_loading.integer)
7070                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7071                 if (r_texture_cubemaps[i].texture)
7072                         R_FreeTexture(r_texture_cubemaps[i].texture);
7073         }
7074         r_texture_numcubemaps = 0;
7075 }
7076
7077 void R_Main_FreeViewCache(void)
7078 {
7079         if (r_refdef.viewcache.entityvisible)
7080                 Mem_Free(r_refdef.viewcache.entityvisible);
7081         if (r_refdef.viewcache.world_pvsbits)
7082                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7083         if (r_refdef.viewcache.world_leafvisible)
7084                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7085         if (r_refdef.viewcache.world_surfacevisible)
7086                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7087         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7088 }
7089
7090 void R_Main_ResizeViewCache(void)
7091 {
7092         int numentities = r_refdef.scene.numentities;
7093         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7094         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7095         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7096         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7097         if (r_refdef.viewcache.maxentities < numentities)
7098         {
7099                 r_refdef.viewcache.maxentities = numentities;
7100                 if (r_refdef.viewcache.entityvisible)
7101                         Mem_Free(r_refdef.viewcache.entityvisible);
7102                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7103         }
7104         if (r_refdef.viewcache.world_numclusters != numclusters)
7105         {
7106                 r_refdef.viewcache.world_numclusters = numclusters;
7107                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7108                 if (r_refdef.viewcache.world_pvsbits)
7109                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7110                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7111         }
7112         if (r_refdef.viewcache.world_numleafs != numleafs)
7113         {
7114                 r_refdef.viewcache.world_numleafs = numleafs;
7115                 if (r_refdef.viewcache.world_leafvisible)
7116                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7117                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7118         }
7119         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7120         {
7121                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7122                 if (r_refdef.viewcache.world_surfacevisible)
7123                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7124                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7125         }
7126 }
7127
7128 extern rtexture_t *loadingscreentexture;
7129 void gl_main_start(void)
7130 {
7131         loadingscreentexture = NULL;
7132         r_texture_blanknormalmap = NULL;
7133         r_texture_white = NULL;
7134         r_texture_grey128 = NULL;
7135         r_texture_black = NULL;
7136         r_texture_whitecube = NULL;
7137         r_texture_normalizationcube = NULL;
7138         r_texture_fogattenuation = NULL;
7139         r_texture_fogheighttexture = NULL;
7140         r_texture_gammaramps = NULL;
7141         r_texture_numcubemaps = 0;
7142
7143         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7144         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7145
7146         switch(vid.renderpath)
7147         {
7148         case RENDERPATH_GL20:
7149         case RENDERPATH_CGGL:
7150         case RENDERPATH_D3D9:
7151         case RENDERPATH_D3D10:
7152         case RENDERPATH_D3D11:
7153                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7154                 Cvar_SetValueQuick(&gl_combine, 1);
7155                 Cvar_SetValueQuick(&r_glsl, 1);
7156                 r_loadnormalmap = true;
7157                 r_loadgloss = true;
7158                 r_loadfog = false;
7159                 break;
7160         case RENDERPATH_GL13:
7161                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7162                 Cvar_SetValueQuick(&gl_combine, 1);
7163                 Cvar_SetValueQuick(&r_glsl, 0);
7164                 r_loadnormalmap = false;
7165                 r_loadgloss = false;
7166                 r_loadfog = true;
7167                 break;
7168         case RENDERPATH_GL11:
7169                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7170                 Cvar_SetValueQuick(&gl_combine, 0);
7171                 Cvar_SetValueQuick(&r_glsl, 0);
7172                 r_loadnormalmap = false;
7173                 r_loadgloss = false;
7174                 r_loadfog = true;
7175                 break;
7176         }
7177
7178         R_AnimCache_Free();
7179         R_FrameData_Reset();
7180
7181         r_numqueries = 0;
7182         r_maxqueries = 0;
7183         memset(r_queries, 0, sizeof(r_queries));
7184
7185         r_qwskincache = NULL;
7186         r_qwskincache_size = 0;
7187
7188         // set up r_skinframe loading system for textures
7189         memset(&r_skinframe, 0, sizeof(r_skinframe));
7190         r_skinframe.loadsequence = 1;
7191         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7192
7193         r_main_texturepool = R_AllocTexturePool();
7194         R_BuildBlankTextures();
7195         R_BuildNoTexture();
7196         if (vid.support.arb_texture_cube_map)
7197         {
7198                 R_BuildWhiteCube();
7199                 R_BuildNormalizationCube();
7200         }
7201         r_texture_fogattenuation = NULL;
7202         r_texture_fogheighttexture = NULL;
7203         r_texture_gammaramps = NULL;
7204         //r_texture_fogintensity = NULL;
7205         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7206         memset(&r_waterstate, 0, sizeof(r_waterstate));
7207         r_glsl_permutation = NULL;
7208         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7209         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7210         glslshaderstring = NULL;
7211 #ifdef SUPPORTCG
7212         r_cg_permutation = NULL;
7213         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7214         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7215         cgshaderstring = NULL;
7216 #endif
7217 #ifdef SUPPORTD3D
7218         r_hlsl_permutation = NULL;
7219         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7220         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7221         hlslshaderstring = NULL;
7222 #endif
7223         memset(&r_svbsp, 0, sizeof (r_svbsp));
7224
7225         r_refdef.fogmasktable_density = 0;
7226 }
7227
7228 void gl_main_shutdown(void)
7229 {
7230         R_AnimCache_Free();
7231         R_FrameData_Reset();
7232
7233         R_Main_FreeViewCache();
7234
7235         switch(vid.renderpath)
7236         {
7237         case RENDERPATH_GL11:
7238         case RENDERPATH_GL13:
7239         case RENDERPATH_GL20:
7240         case RENDERPATH_CGGL:
7241                 if (r_maxqueries)
7242                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7243                 break;
7244         case RENDERPATH_D3D9:
7245                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7246                 break;
7247         case RENDERPATH_D3D10:
7248                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7249                 break;
7250         case RENDERPATH_D3D11:
7251                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7252                 break;
7253         }
7254
7255         r_numqueries = 0;
7256         r_maxqueries = 0;
7257         memset(r_queries, 0, sizeof(r_queries));
7258
7259         r_qwskincache = NULL;
7260         r_qwskincache_size = 0;
7261
7262         // clear out the r_skinframe state
7263         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7264         memset(&r_skinframe, 0, sizeof(r_skinframe));
7265
7266         if (r_svbsp.nodes)
7267                 Mem_Free(r_svbsp.nodes);
7268         memset(&r_svbsp, 0, sizeof (r_svbsp));
7269         R_FreeTexturePool(&r_main_texturepool);
7270         loadingscreentexture = NULL;
7271         r_texture_blanknormalmap = NULL;
7272         r_texture_white = NULL;
7273         r_texture_grey128 = NULL;
7274         r_texture_black = NULL;
7275         r_texture_whitecube = NULL;
7276         r_texture_normalizationcube = NULL;
7277         r_texture_fogattenuation = NULL;
7278         r_texture_fogheighttexture = NULL;
7279         r_texture_gammaramps = NULL;
7280         r_texture_numcubemaps = 0;
7281         //r_texture_fogintensity = NULL;
7282         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7283         memset(&r_waterstate, 0, sizeof(r_waterstate));
7284         R_GLSL_Restart_f();
7285 }
7286
7287 extern void CL_ParseEntityLump(char *entitystring);
7288 void gl_main_newmap(void)
7289 {
7290         // FIXME: move this code to client
7291         char *entities, entname[MAX_QPATH];
7292         if (r_qwskincache)
7293                 Mem_Free(r_qwskincache);
7294         r_qwskincache = NULL;
7295         r_qwskincache_size = 0;
7296         if (cl.worldmodel)
7297         {
7298                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7299                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7300                 {
7301                         CL_ParseEntityLump(entities);
7302                         Mem_Free(entities);
7303                         return;
7304                 }
7305                 if (cl.worldmodel->brush.entities)
7306                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7307         }
7308         R_Main_FreeViewCache();
7309
7310         R_FrameData_Reset();
7311 }
7312
7313 void GL_Main_Init(void)
7314 {
7315         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7316
7317         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7318         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7319         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7320         if (gamemode == GAME_NEHAHRA)
7321         {
7322                 Cvar_RegisterVariable (&gl_fogenable);
7323                 Cvar_RegisterVariable (&gl_fogdensity);
7324                 Cvar_RegisterVariable (&gl_fogred);
7325                 Cvar_RegisterVariable (&gl_foggreen);
7326                 Cvar_RegisterVariable (&gl_fogblue);
7327                 Cvar_RegisterVariable (&gl_fogstart);
7328                 Cvar_RegisterVariable (&gl_fogend);
7329                 Cvar_RegisterVariable (&gl_skyclip);
7330         }
7331         Cvar_RegisterVariable(&r_motionblur);
7332         Cvar_RegisterVariable(&r_motionblur_maxblur);
7333         Cvar_RegisterVariable(&r_motionblur_bmin);
7334         Cvar_RegisterVariable(&r_motionblur_vmin);
7335         Cvar_RegisterVariable(&r_motionblur_vmax);
7336         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7337         Cvar_RegisterVariable(&r_motionblur_randomize);
7338         Cvar_RegisterVariable(&r_damageblur);
7339         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7340         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7341         Cvar_RegisterVariable(&r_equalize_entities_by);
7342         Cvar_RegisterVariable(&r_equalize_entities_to);
7343         Cvar_RegisterVariable(&r_depthfirst);
7344         Cvar_RegisterVariable(&r_useinfinitefarclip);
7345         Cvar_RegisterVariable(&r_farclip_base);
7346         Cvar_RegisterVariable(&r_farclip_world);
7347         Cvar_RegisterVariable(&r_nearclip);
7348         Cvar_RegisterVariable(&r_showbboxes);
7349         Cvar_RegisterVariable(&r_showsurfaces);
7350         Cvar_RegisterVariable(&r_showtris);
7351         Cvar_RegisterVariable(&r_shownormals);
7352         Cvar_RegisterVariable(&r_showlighting);
7353         Cvar_RegisterVariable(&r_showshadowvolumes);
7354         Cvar_RegisterVariable(&r_showcollisionbrushes);
7355         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7356         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7357         Cvar_RegisterVariable(&r_showdisabledepthtest);
7358         Cvar_RegisterVariable(&r_drawportals);
7359         Cvar_RegisterVariable(&r_drawentities);
7360         Cvar_RegisterVariable(&r_draw2d);
7361         Cvar_RegisterVariable(&r_drawworld);
7362         Cvar_RegisterVariable(&r_cullentities_trace);
7363         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7364         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7365         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7366         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7367         Cvar_RegisterVariable(&r_drawviewmodel);
7368         Cvar_RegisterVariable(&r_drawexteriormodel);
7369         Cvar_RegisterVariable(&r_speeds);
7370         Cvar_RegisterVariable(&r_fullbrights);
7371         Cvar_RegisterVariable(&r_wateralpha);
7372         Cvar_RegisterVariable(&r_dynamic);
7373         Cvar_RegisterVariable(&r_fakelight);
7374         Cvar_RegisterVariable(&r_fakelight_intensity);
7375         Cvar_RegisterVariable(&r_fullbright);
7376         Cvar_RegisterVariable(&r_shadows);
7377         Cvar_RegisterVariable(&r_shadows_darken);
7378         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7379         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7380         Cvar_RegisterVariable(&r_shadows_throwdistance);
7381         Cvar_RegisterVariable(&r_shadows_throwdirection);
7382         Cvar_RegisterVariable(&r_shadows_focus);
7383         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7384         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7385         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7386         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7387         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7388         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7389         Cvar_RegisterVariable(&r_fog_exp2);
7390         Cvar_RegisterVariable(&r_drawfog);
7391         Cvar_RegisterVariable(&r_transparentdepthmasking);
7392         Cvar_RegisterVariable(&r_texture_dds_load);
7393         Cvar_RegisterVariable(&r_texture_dds_save);
7394         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7395         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7396         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7397         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7398         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7399         Cvar_RegisterVariable(&r_textureunits);
7400         Cvar_RegisterVariable(&gl_combine);
7401         Cvar_RegisterVariable(&r_glsl);
7402         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7403         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7404         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7405         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7406         Cvar_RegisterVariable(&r_glsl_postprocess);
7407         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7408         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7409         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7410         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7411         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7412         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7413         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7414         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7415
7416         Cvar_RegisterVariable(&r_water);
7417         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7418         Cvar_RegisterVariable(&r_water_clippingplanebias);
7419         Cvar_RegisterVariable(&r_water_refractdistort);
7420         Cvar_RegisterVariable(&r_water_reflectdistort);
7421         Cvar_RegisterVariable(&r_water_scissormode);
7422         Cvar_RegisterVariable(&r_lerpsprites);
7423         Cvar_RegisterVariable(&r_lerpmodels);
7424         Cvar_RegisterVariable(&r_lerplightstyles);
7425         Cvar_RegisterVariable(&r_waterscroll);
7426         Cvar_RegisterVariable(&r_bloom);
7427         Cvar_RegisterVariable(&r_bloom_colorscale);
7428         Cvar_RegisterVariable(&r_bloom_brighten);
7429         Cvar_RegisterVariable(&r_bloom_blur);
7430         Cvar_RegisterVariable(&r_bloom_resolution);
7431         Cvar_RegisterVariable(&r_bloom_colorexponent);
7432         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7433         Cvar_RegisterVariable(&r_hdr);
7434         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7435         Cvar_RegisterVariable(&r_hdr_glowintensity);
7436         Cvar_RegisterVariable(&r_hdr_range);
7437         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7438         Cvar_RegisterVariable(&developer_texturelogging);
7439         Cvar_RegisterVariable(&gl_lightmaps);
7440         Cvar_RegisterVariable(&r_test);
7441         Cvar_RegisterVariable(&r_glsl_saturation);
7442         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7443         Cvar_RegisterVariable(&r_framedatasize);
7444         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7445                 Cvar_SetValue("r_fullbrights", 0);
7446         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7447
7448         Cvar_RegisterVariable(&r_track_sprites);
7449         Cvar_RegisterVariable(&r_track_sprites_flags);
7450         Cvar_RegisterVariable(&r_track_sprites_scalew);
7451         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7452         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7453         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7454 }
7455
7456 extern void R_Textures_Init(void);
7457 extern void GL_Draw_Init(void);
7458 extern void GL_Main_Init(void);
7459 extern void R_Shadow_Init(void);
7460 extern void R_Sky_Init(void);
7461 extern void GL_Surf_Init(void);
7462 extern void R_Particles_Init(void);
7463 extern void R_Explosion_Init(void);
7464 extern void gl_backend_init(void);
7465 extern void Sbar_Init(void);
7466 extern void R_LightningBeams_Init(void);
7467 extern void Mod_RenderInit(void);
7468 extern void Font_Init(void);
7469
7470 void Render_Init(void)
7471 {
7472         gl_backend_init();
7473         R_Textures_Init();
7474         GL_Main_Init();
7475         Font_Init();
7476         GL_Draw_Init();
7477         R_Shadow_Init();
7478         R_Sky_Init();
7479         GL_Surf_Init();
7480         Sbar_Init();
7481         R_Particles_Init();
7482         R_Explosion_Init();
7483         R_LightningBeams_Init();
7484         Mod_RenderInit();
7485 }
7486
7487 /*
7488 ===============
7489 GL_Init
7490 ===============
7491 */
7492 extern char *ENGINE_EXTENSIONS;
7493 void GL_Init (void)
7494 {
7495         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7496         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7497         gl_version = (const char *)qglGetString(GL_VERSION);
7498         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7499
7500         if (!gl_extensions)
7501                 gl_extensions = "";
7502         if (!gl_platformextensions)
7503                 gl_platformextensions = "";
7504
7505         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7506         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7507         Con_Printf("GL_VERSION: %s\n", gl_version);
7508         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7509         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7510
7511         VID_CheckExtensions();
7512
7513         // LordHavoc: report supported extensions
7514         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7515
7516         // clear to black (loading plaque will be seen over this)
7517         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7518 }
7519
7520 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7521 {
7522         int i;
7523         mplane_t *p;
7524         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7525         {
7526                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7527                 if (i == 4)
7528                         continue;
7529                 p = r_refdef.view.frustum + i;
7530                 switch(p->signbits)
7531                 {
7532                 default:
7533                 case 0:
7534                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7535                                 return true;
7536                         break;
7537                 case 1:
7538                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7539                                 return true;
7540                         break;
7541                 case 2:
7542                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7543                                 return true;
7544                         break;
7545                 case 3:
7546                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7547                                 return true;
7548                         break;
7549                 case 4:
7550                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7551                                 return true;
7552                         break;
7553                 case 5:
7554                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7555                                 return true;
7556                         break;
7557                 case 6:
7558                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7559                                 return true;
7560                         break;
7561                 case 7:
7562                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7563                                 return true;
7564                         break;
7565                 }
7566         }
7567         return false;
7568 }
7569
7570 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7571 {
7572         int i;
7573         const mplane_t *p;
7574         for (i = 0;i < numplanes;i++)
7575         {
7576                 p = planes + i;
7577                 switch(p->signbits)
7578                 {
7579                 default:
7580                 case 0:
7581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7582                                 return true;
7583                         break;
7584                 case 1:
7585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7586                                 return true;
7587                         break;
7588                 case 2:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 3:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 4:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 5:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 6:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 7:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 }
7613         }
7614         return false;
7615 }
7616
7617 //==================================================================================
7618
7619 // LordHavoc: this stores temporary data used within the same frame
7620
7621 qboolean r_framedata_failed;
7622 static size_t r_framedata_size;
7623 static size_t r_framedata_current;
7624 static void *r_framedata_base;
7625
7626 void R_FrameData_Reset(void)
7627 {
7628         if (r_framedata_base)
7629                 Mem_Free(r_framedata_base);
7630         r_framedata_base = NULL;
7631         r_framedata_size = 0;
7632         r_framedata_current = 0;
7633         r_framedata_failed = false;
7634 }
7635
7636 void R_FrameData_NewFrame(void)
7637 {
7638         size_t wantedsize;
7639         if (r_framedata_failed)
7640                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7641         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7642         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7643         if (r_framedata_size != wantedsize)
7644         {
7645                 r_framedata_size = wantedsize;
7646                 if (r_framedata_base)
7647                         Mem_Free(r_framedata_base);
7648                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7649         }
7650         r_framedata_current = 0;
7651         r_framedata_failed = false;
7652 }
7653
7654 void *R_FrameData_Alloc(size_t size)
7655 {
7656         void *data;
7657
7658         // align to 16 byte boundary
7659         size = (size + 15) & ~15;
7660         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7661         r_framedata_current += size;
7662
7663         // check overflow
7664         if (r_framedata_current > r_framedata_size)
7665                 r_framedata_failed = true;
7666
7667         // return NULL on everything after a failure
7668         if (r_framedata_failed)
7669                 return NULL;
7670
7671         return data;
7672 }
7673
7674 void *R_FrameData_Store(size_t size, void *data)
7675 {
7676         void *d = R_FrameData_Alloc(size);
7677         if (d)
7678                 memcpy(d, data, size);
7679         return d;
7680 }
7681
7682 //==================================================================================
7683
7684 // LordHavoc: animcache originally written by Echon, rewritten since then
7685
7686 /**
7687  * Animation cache prevents re-generating mesh data for an animated model
7688  * multiple times in one frame for lighting, shadowing, reflections, etc.
7689  */
7690
7691 void R_AnimCache_Free(void)
7692 {
7693 }
7694
7695 void R_AnimCache_ClearCache(void)
7696 {
7697         int i;
7698         entity_render_t *ent;
7699
7700         for (i = 0;i < r_refdef.scene.numentities;i++)
7701         {
7702                 ent = r_refdef.scene.entities[i];
7703                 ent->animcache_vertex3f = NULL;
7704                 ent->animcache_normal3f = NULL;
7705                 ent->animcache_svector3f = NULL;
7706                 ent->animcache_tvector3f = NULL;
7707                 ent->animcache_vertexposition = NULL;
7708                 ent->animcache_vertexmesh = NULL;
7709                 ent->animcache_vertexpositionbuffer = NULL;
7710                 ent->animcache_vertexmeshbuffer = NULL;
7711         }
7712 }
7713
7714 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7715 {
7716         int i;
7717
7718         // identical memory layout, so no need to allocate...
7719         // this also provides the vertexposition structure to everything, e.g.
7720         // depth masked rendering currently uses it even if having separate
7721         // arrays
7722         // NOTE: get rid of this optimization if changing it to e.g. 4f
7723         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7724
7725         // TODO:
7726         // get rid of following uses of VERTEXPOSITION, change to the array:
7727         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7728         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7729         // R_DrawTextureSurfaceList_DepthOnly
7730         // R_Q1BSP_DrawShadowMap
7731
7732         switch(vid.renderpath)
7733         {
7734         case RENDERPATH_GL20:
7735         case RENDERPATH_CGGL:
7736                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7737                 if (gl_mesh_separatearrays.integer)
7738                         return;
7739                 break;
7740         case RENDERPATH_D3D9:
7741         case RENDERPATH_D3D10:
7742         case RENDERPATH_D3D11:
7743                 // always need the meshbuffers
7744                 break;
7745         case RENDERPATH_GL13:
7746         case RENDERPATH_GL11:
7747                 // never need the meshbuffers
7748                 return;
7749         }
7750
7751         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7752                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7753         /*
7754         if (!ent->animcache_vertexposition)
7755                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7756         */
7757         if (ent->animcache_vertexposition)
7758         {
7759                 /*
7760                 for (i = 0;i < numvertices;i++)
7761                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7762                 */
7763                 // TODO: upload vertex buffer?
7764         }
7765         if (ent->animcache_vertexmesh)
7766         {
7767                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7768                 for (i = 0;i < numvertices;i++)
7769                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7770                 if (ent->animcache_svector3f)
7771                         for (i = 0;i < numvertices;i++)
7772                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7773                 if (ent->animcache_tvector3f)
7774                         for (i = 0;i < numvertices;i++)
7775                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7776                 if (ent->animcache_normal3f)
7777                         for (i = 0;i < numvertices;i++)
7778                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7779                 // TODO: upload vertex buffer?
7780         }
7781 }
7782
7783 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7784 {
7785         dp_model_t *model = ent->model;
7786         int numvertices;
7787         // see if it's already cached this frame
7788         if (ent->animcache_vertex3f)
7789         {
7790                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7791                 if (wantnormals || wanttangents)
7792                 {
7793                         if (ent->animcache_normal3f)
7794                                 wantnormals = false;
7795                         if (ent->animcache_svector3f)
7796                                 wanttangents = false;
7797                         if (wantnormals || wanttangents)
7798                         {
7799                                 numvertices = model->surfmesh.num_vertices;
7800                                 if (wantnormals)
7801                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7802                                 if (wanttangents)
7803                                 {
7804                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7805                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7806                                 }
7807                                 if (!r_framedata_failed)
7808                                 {
7809                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7810                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7811                                 }
7812                         }
7813                 }
7814         }
7815         else
7816         {
7817                 // see if this ent is worth caching
7818                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7819                         return false;
7820                 // get some memory for this entity and generate mesh data
7821                 numvertices = model->surfmesh.num_vertices;
7822                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7823                 if (wantnormals)
7824                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7825                 if (wanttangents)
7826                 {
7827                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7828                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7829                 }
7830                 if (!r_framedata_failed)
7831                 {
7832                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7833                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7834                 }
7835         }
7836         return !r_framedata_failed;
7837 }
7838
7839 void R_AnimCache_CacheVisibleEntities(void)
7840 {
7841         int i;
7842         qboolean wantnormals = true;
7843         qboolean wanttangents = !r_showsurfaces.integer;
7844
7845         switch(vid.renderpath)
7846         {
7847         case RENDERPATH_GL20:
7848         case RENDERPATH_CGGL:
7849         case RENDERPATH_D3D9:
7850         case RENDERPATH_D3D10:
7851         case RENDERPATH_D3D11:
7852                 break;
7853         case RENDERPATH_GL13:
7854         case RENDERPATH_GL11:
7855                 wanttangents = false;
7856                 break;
7857         }
7858
7859         if (r_shownormals.integer)
7860                 wanttangents = wantnormals = true;
7861
7862         // TODO: thread this
7863         // NOTE: R_PrepareRTLights() also caches entities
7864
7865         for (i = 0;i < r_refdef.scene.numentities;i++)
7866                 if (r_refdef.viewcache.entityvisible[i])
7867                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7868 }
7869
7870 //==================================================================================
7871
7872 static void R_View_UpdateEntityLighting (void)
7873 {
7874         int i;
7875         entity_render_t *ent;
7876         vec3_t tempdiffusenormal, avg;
7877         vec_t f, fa, fd, fdd;
7878         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7879
7880         for (i = 0;i < r_refdef.scene.numentities;i++)
7881         {
7882                 ent = r_refdef.scene.entities[i];
7883
7884                 // skip unseen models
7885                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7886                         continue;
7887
7888                 // skip bsp models
7889                 if (ent->model && ent->model->brush.num_leafs)
7890                 {
7891                         // TODO: use modellight for r_ambient settings on world?
7892                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7893                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7894                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7895                         continue;
7896                 }
7897
7898                 // fetch the lighting from the worldmodel data
7899                 VectorClear(ent->modellight_ambient);
7900                 VectorClear(ent->modellight_diffuse);
7901                 VectorClear(tempdiffusenormal);
7902                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7903                 {
7904                         vec3_t org;
7905                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7906
7907                         // complete lightning for lit sprites
7908                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7909                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7910                         {
7911                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7912                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7913                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7914                         }
7915                         else
7916                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7917
7918                         if(ent->flags & RENDER_EQUALIZE)
7919                         {
7920                                 // first fix up ambient lighting...
7921                                 if(r_equalize_entities_minambient.value > 0)
7922                                 {
7923                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7924                                         if(fd > 0)
7925                                         {
7926                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7927                                                 if(fa < r_equalize_entities_minambient.value * fd)
7928                                                 {
7929                                                         // solve:
7930                                                         //   fa'/fd' = minambient
7931                                                         //   fa'+0.25*fd' = fa+0.25*fd
7932                                                         //   ...
7933                                                         //   fa' = fd' * minambient
7934                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7935                                                         //   ...
7936                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7937                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7938                                                         //   ...
7939                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7940                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
7941                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7942                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7943                                                 }
7944                                         }
7945                                 }
7946
7947                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7948                                 {
7949                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7950                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7951                                         if(f > 0)
7952                                         {
7953                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7954                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7955                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7956                                         }
7957                                 }
7958                         }
7959                 }
7960                 else // highly rare
7961                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7962
7963                 // move the light direction into modelspace coordinates for lighting code
7964                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7965                 if(VectorLength2(ent->modellight_lightdir) == 0)
7966                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7967                 VectorNormalize(ent->modellight_lightdir);
7968         }
7969 }
7970
7971 #define MAX_LINEOFSIGHTTRACES 64
7972
7973 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7974 {
7975         int i;
7976         vec3_t boxmins, boxmaxs;
7977         vec3_t start;
7978         vec3_t end;
7979         dp_model_t *model = r_refdef.scene.worldmodel;
7980
7981         if (!model || !model->brush.TraceLineOfSight)
7982                 return true;
7983
7984         // expand the box a little
7985         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7986         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7987         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7988         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7989         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7990         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7991
7992         // return true if eye is inside enlarged box
7993         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7994                 return true;
7995
7996         // try center
7997         VectorCopy(eye, start);
7998         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7999         if (model->brush.TraceLineOfSight(model, start, end))
8000                 return true;
8001
8002         // try various random positions
8003         for (i = 0;i < numsamples;i++)
8004         {
8005                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8006                 if (model->brush.TraceLineOfSight(model, start, end))
8007                         return true;
8008         }
8009
8010         return false;
8011 }
8012
8013
8014 static void R_View_UpdateEntityVisible (void)
8015 {
8016         int i;
8017         int renderimask;
8018         int samples;
8019         entity_render_t *ent;
8020
8021         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8022                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8023                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8024                 :                                                          RENDER_EXTERIORMODEL;
8025         if (!r_drawviewmodel.integer)
8026                 renderimask |= RENDER_VIEWMODEL;
8027         if (!r_drawexteriormodel.integer)
8028                 renderimask |= RENDER_EXTERIORMODEL;
8029         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8030         {
8031                 // worldmodel can check visibility
8032                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8033                 for (i = 0;i < r_refdef.scene.numentities;i++)
8034                 {
8035                         ent = r_refdef.scene.entities[i];
8036                         if (!(ent->flags & renderimask))
8037                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8038                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
8039                                 r_refdef.viewcache.entityvisible[i] = true;
8040                 }
8041                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8042                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8043                 {
8044                         for (i = 0;i < r_refdef.scene.numentities;i++)
8045                         {
8046                                 ent = r_refdef.scene.entities[i];
8047                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8048                                 {
8049                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8050                                         if (samples < 0)
8051                                                 continue; // temp entities do pvs only
8052                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8053                                                 ent->last_trace_visibility = realtime;
8054                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8055                                                 r_refdef.viewcache.entityvisible[i] = 0;
8056                                 }
8057                         }
8058                 }
8059         }
8060         else
8061         {
8062                 // no worldmodel or it can't check visibility
8063                 for (i = 0;i < r_refdef.scene.numentities;i++)
8064                 {
8065                         ent = r_refdef.scene.entities[i];
8066                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
8067                 }
8068         }
8069 }
8070
8071 /// only used if skyrendermasked, and normally returns false
8072 int R_DrawBrushModelsSky (void)
8073 {
8074         int i, sky;
8075         entity_render_t *ent;
8076
8077         sky = false;
8078         for (i = 0;i < r_refdef.scene.numentities;i++)
8079         {
8080                 if (!r_refdef.viewcache.entityvisible[i])
8081                         continue;
8082                 ent = r_refdef.scene.entities[i];
8083                 if (!ent->model || !ent->model->DrawSky)
8084                         continue;
8085                 ent->model->DrawSky(ent);
8086                 sky = true;
8087         }
8088         return sky;
8089 }
8090
8091 static void R_DrawNoModel(entity_render_t *ent);
8092 static void R_DrawModels(void)
8093 {
8094         int i;
8095         entity_render_t *ent;
8096
8097         for (i = 0;i < r_refdef.scene.numentities;i++)
8098         {
8099                 if (!r_refdef.viewcache.entityvisible[i])
8100                         continue;
8101                 ent = r_refdef.scene.entities[i];
8102                 r_refdef.stats.entities++;
8103                 if (ent->model && ent->model->Draw != NULL)
8104                         ent->model->Draw(ent);
8105                 else
8106                         R_DrawNoModel(ent);
8107         }
8108 }
8109
8110 static void R_DrawModelsDepth(void)
8111 {
8112         int i;
8113         entity_render_t *ent;
8114
8115         for (i = 0;i < r_refdef.scene.numentities;i++)
8116         {
8117                 if (!r_refdef.viewcache.entityvisible[i])
8118                         continue;
8119                 ent = r_refdef.scene.entities[i];
8120                 if (ent->model && ent->model->DrawDepth != NULL)
8121                         ent->model->DrawDepth(ent);
8122         }
8123 }
8124
8125 static void R_DrawModelsDebug(void)
8126 {
8127         int i;
8128         entity_render_t *ent;
8129
8130         for (i = 0;i < r_refdef.scene.numentities;i++)
8131         {
8132                 if (!r_refdef.viewcache.entityvisible[i])
8133                         continue;
8134                 ent = r_refdef.scene.entities[i];
8135                 if (ent->model && ent->model->DrawDebug != NULL)
8136                         ent->model->DrawDebug(ent);
8137         }
8138 }
8139
8140 static void R_DrawModelsAddWaterPlanes(void)
8141 {
8142         int i;
8143         entity_render_t *ent;
8144
8145         for (i = 0;i < r_refdef.scene.numentities;i++)
8146         {
8147                 if (!r_refdef.viewcache.entityvisible[i])
8148                         continue;
8149                 ent = r_refdef.scene.entities[i];
8150                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8151                         ent->model->DrawAddWaterPlanes(ent);
8152         }
8153 }
8154
8155 static void R_View_SetFrustum(const int *scissor)
8156 {
8157         int i;
8158         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8159         vec3_t forward, left, up, origin, v;
8160
8161         if(scissor)
8162         {
8163                 // flipped x coordinates (because x points left here)
8164                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8165                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8166
8167                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8168                 switch(vid.renderpath)
8169                 {
8170                         case RENDERPATH_D3D9:
8171                         case RENDERPATH_D3D10:
8172                         case RENDERPATH_D3D11:
8173                                 // non-flipped y coordinates
8174                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8175                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8176                                 break;
8177                         case RENDERPATH_GL11:
8178                         case RENDERPATH_GL13:
8179                         case RENDERPATH_GL20:
8180                         case RENDERPATH_CGGL:
8181                                 // non-flipped y coordinates
8182                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8183                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8184                                 break;
8185                 }
8186         }
8187
8188         // we can't trust r_refdef.view.forward and friends in reflected scenes
8189         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8190
8191 #if 0
8192         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8193         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8194         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8195         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8196         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8197         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8198         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8199         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8200         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8201         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8202         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8203         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8204 #endif
8205
8206 #if 0
8207         zNear = r_refdef.nearclip;
8208         nudge = 1.0 - 1.0 / (1<<23);
8209         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8210         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8211         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8212         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8213         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8214         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8215         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8216         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8217 #endif
8218
8219
8220
8221 #if 0
8222         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8223         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8224         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8225         r_refdef.view.frustum[0].dist = m[15] - m[12];
8226
8227         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8228         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8229         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8230         r_refdef.view.frustum[1].dist = m[15] + m[12];
8231
8232         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8233         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8234         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8235         r_refdef.view.frustum[2].dist = m[15] - m[13];
8236
8237         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8238         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8239         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8240         r_refdef.view.frustum[3].dist = m[15] + m[13];
8241
8242         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8243         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8244         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8245         r_refdef.view.frustum[4].dist = m[15] - m[14];
8246
8247         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8248         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8249         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8250         r_refdef.view.frustum[5].dist = m[15] + m[14];
8251 #endif
8252
8253         if (r_refdef.view.useperspective)
8254         {
8255                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8256                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8257                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8258                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8259                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8260
8261                 // then the normals from the corners relative to origin
8262                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8263                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8264                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8265                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8266
8267                 // in a NORMAL view, forward cross left == up
8268                 // in a REFLECTED view, forward cross left == down
8269                 // so our cross products above need to be adjusted for a left handed coordinate system
8270                 CrossProduct(forward, left, v);
8271                 if(DotProduct(v, up) < 0)
8272                 {
8273                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8274                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8275                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8276                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8277                 }
8278
8279                 // Leaving those out was a mistake, those were in the old code, and they
8280                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8281                 // I couldn't reproduce it after adding those normalizations. --blub
8282                 VectorNormalize(r_refdef.view.frustum[0].normal);
8283                 VectorNormalize(r_refdef.view.frustum[1].normal);
8284                 VectorNormalize(r_refdef.view.frustum[2].normal);
8285                 VectorNormalize(r_refdef.view.frustum[3].normal);
8286
8287                 // make the corners absolute
8288                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8289                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8290                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8291                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8292
8293                 // one more normal
8294                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8295
8296                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8297                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8298                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8299                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8300                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8301         }
8302         else
8303         {
8304                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8305                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8306                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8307                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8308                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8309                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8310                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8311                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8312                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8313                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8314         }
8315         r_refdef.view.numfrustumplanes = 5;
8316
8317         if (r_refdef.view.useclipplane)
8318         {
8319                 r_refdef.view.numfrustumplanes = 6;
8320                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8321         }
8322
8323         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8324                 PlaneClassify(r_refdef.view.frustum + i);
8325
8326         // LordHavoc: note to all quake engine coders, Quake had a special case
8327         // for 90 degrees which assumed a square view (wrong), so I removed it,
8328         // Quake2 has it disabled as well.
8329
8330         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8331         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8332         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8333         //PlaneClassify(&frustum[0]);
8334
8335         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8336         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8337         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8338         //PlaneClassify(&frustum[1]);
8339
8340         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8341         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8342         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8343         //PlaneClassify(&frustum[2]);
8344
8345         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8346         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8347         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8348         //PlaneClassify(&frustum[3]);
8349
8350         // nearclip plane
8351         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8352         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8353         //PlaneClassify(&frustum[4]);
8354 }
8355
8356 void R_View_UpdateWithScissor(const int *myscissor)
8357 {
8358         R_Main_ResizeViewCache();
8359         R_View_SetFrustum(myscissor);
8360         R_View_WorldVisibility(r_refdef.view.useclipplane);
8361         R_View_UpdateEntityVisible();
8362         R_View_UpdateEntityLighting();
8363 }
8364
8365 void R_View_Update(void)
8366 {
8367         R_Main_ResizeViewCache();
8368         R_View_SetFrustum(NULL);
8369         R_View_WorldVisibility(r_refdef.view.useclipplane);
8370         R_View_UpdateEntityVisible();
8371         R_View_UpdateEntityLighting();
8372 }
8373
8374 void R_SetupView(qboolean allowwaterclippingplane)
8375 {
8376         const float *customclipplane = NULL;
8377         float plane[4];
8378         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8379         {
8380                 // LordHavoc: couldn't figure out how to make this approach the
8381                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8382                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8383                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8384                         dist = r_refdef.view.clipplane.dist;
8385                 plane[0] = r_refdef.view.clipplane.normal[0];
8386                 plane[1] = r_refdef.view.clipplane.normal[1];
8387                 plane[2] = r_refdef.view.clipplane.normal[2];
8388                 plane[3] = dist;
8389                 customclipplane = plane;
8390         }
8391
8392         if (!r_refdef.view.useperspective)
8393                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
8394         else if (vid.stencil && r_useinfinitefarclip.integer)
8395                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
8396         else
8397                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
8398         R_SetViewport(&r_refdef.view.viewport);
8399 }
8400
8401 void R_EntityMatrix(const matrix4x4_t *matrix)
8402 {
8403         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8404         {
8405                 gl_modelmatrixchanged = false;
8406                 gl_modelmatrix = *matrix;
8407                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8408                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8409                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8410                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8411                 CHECKGLERROR
8412                 switch(vid.renderpath)
8413                 {
8414                 case RENDERPATH_D3D9:
8415 #ifdef SUPPORTD3D
8416                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8417                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8418 #endif
8419                         break;
8420                 case RENDERPATH_D3D10:
8421                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8422                         break;
8423                 case RENDERPATH_D3D11:
8424                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8425                         break;
8426                 case RENDERPATH_GL20:
8427                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8428                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8429                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8430                         break;
8431                 case RENDERPATH_CGGL:
8432 #ifdef SUPPORTCG
8433                         CHECKCGERROR
8434                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8435                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8436                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8437 #endif
8438                         break;
8439                 case RENDERPATH_GL13:
8440                 case RENDERPATH_GL11:
8441                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8442                         break;
8443                 }
8444         }
8445 }
8446
8447 void R_ResetViewRendering2D(void)
8448 {
8449         r_viewport_t viewport;
8450         DrawQ_Finish();
8451
8452         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8453         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
8454         R_SetViewport(&viewport);
8455         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8456         GL_Color(1, 1, 1, 1);
8457         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8458         GL_BlendFunc(GL_ONE, GL_ZERO);
8459         GL_AlphaTest(false);
8460         GL_ScissorTest(false);
8461         GL_DepthMask(false);
8462         GL_DepthRange(0, 1);
8463         GL_DepthTest(false);
8464         GL_DepthFunc(GL_LEQUAL);
8465         R_EntityMatrix(&identitymatrix);
8466         R_Mesh_ResetTextureState();
8467         GL_PolygonOffset(0, 0);
8468         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8469         switch(vid.renderpath)
8470         {
8471         case RENDERPATH_GL11:
8472         case RENDERPATH_GL13:
8473         case RENDERPATH_GL20:
8474         case RENDERPATH_CGGL:
8475                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8476                 break;
8477         case RENDERPATH_D3D9:
8478         case RENDERPATH_D3D10:
8479         case RENDERPATH_D3D11:
8480                 break;
8481         }
8482         GL_CullFace(GL_NONE);
8483 }
8484
8485 void R_ResetViewRendering3D(void)
8486 {
8487         DrawQ_Finish();
8488
8489         R_SetupView(true);
8490         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8491         GL_Color(1, 1, 1, 1);
8492         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8493         GL_BlendFunc(GL_ONE, GL_ZERO);
8494         GL_AlphaTest(false);
8495         GL_ScissorTest(true);
8496         GL_DepthMask(true);
8497         GL_DepthRange(0, 1);
8498         GL_DepthTest(true);
8499         GL_DepthFunc(GL_LEQUAL);
8500         R_EntityMatrix(&identitymatrix);
8501         R_Mesh_ResetTextureState();
8502         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8503         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8504         switch(vid.renderpath)
8505         {
8506         case RENDERPATH_GL11:
8507         case RENDERPATH_GL13:
8508         case RENDERPATH_GL20:
8509         case RENDERPATH_CGGL:
8510                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8511                 break;
8512         case RENDERPATH_D3D9:
8513         case RENDERPATH_D3D10:
8514         case RENDERPATH_D3D11:
8515                 break;
8516         }
8517         GL_CullFace(r_refdef.view.cullface_back);
8518 }
8519
8520 /*
8521 ================
8522 R_RenderView_UpdateViewVectors
8523 ================
8524 */
8525 static void R_RenderView_UpdateViewVectors(void)
8526 {
8527         // break apart the view matrix into vectors for various purposes
8528         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8529         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8530         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8531         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8532         // make an inverted copy of the view matrix for tracking sprites
8533         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8534 }
8535
8536 void R_RenderScene(void);
8537 void R_RenderWaterPlanes(void);
8538
8539 static void R_Water_StartFrame(void)
8540 {
8541         int i;
8542         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8543         r_waterstate_waterplane_t *p;
8544
8545         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8546                 return;
8547
8548         switch(vid.renderpath)
8549         {
8550         case RENDERPATH_GL20:
8551         case RENDERPATH_CGGL:
8552         case RENDERPATH_D3D9:
8553         case RENDERPATH_D3D10:
8554         case RENDERPATH_D3D11:
8555                 break;
8556         case RENDERPATH_GL13:
8557         case RENDERPATH_GL11:
8558                 return;
8559         }
8560
8561         // set waterwidth and waterheight to the water resolution that will be
8562         // used (often less than the screen resolution for faster rendering)
8563         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8564         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8565
8566         // calculate desired texture sizes
8567         // can't use water if the card does not support the texture size
8568         if (!r_water.integer || r_showsurfaces.integer)
8569                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8570         else if (vid.support.arb_texture_non_power_of_two)
8571         {
8572                 texturewidth = waterwidth;
8573                 textureheight = waterheight;
8574                 camerawidth = waterwidth;
8575                 cameraheight = waterheight;
8576         }
8577         else
8578         {
8579                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8580                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8581                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8582                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8583         }
8584
8585         // allocate textures as needed
8586         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8587         {
8588                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8589                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8590                 {
8591                         if (p->texture_refraction)
8592                                 R_FreeTexture(p->texture_refraction);
8593                         p->texture_refraction = NULL;
8594                         if (p->texture_reflection)
8595                                 R_FreeTexture(p->texture_reflection);
8596                         p->texture_reflection = NULL;
8597                         if (p->texture_camera)
8598                                 R_FreeTexture(p->texture_camera);
8599                         p->texture_camera = NULL;
8600                 }
8601                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8602                 r_waterstate.texturewidth = texturewidth;
8603                 r_waterstate.textureheight = textureheight;
8604                 r_waterstate.camerawidth = camerawidth;
8605                 r_waterstate.cameraheight = cameraheight;
8606         }
8607
8608         if (r_waterstate.texturewidth)
8609         {
8610                 r_waterstate.enabled = true;
8611
8612                 // when doing a reduced render (HDR) we want to use a smaller area
8613                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8614                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8615
8616                 // set up variables that will be used in shader setup
8617                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8618                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8619                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8620                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8621         }
8622
8623         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8624         r_waterstate.numwaterplanes = 0;
8625 }
8626
8627 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8628 {
8629         int triangleindex, planeindex;
8630         const int *e;
8631         vec3_t vert[3];
8632         vec3_t normal;
8633         vec3_t center;
8634         mplane_t plane;
8635         r_waterstate_waterplane_t *p;
8636         texture_t *t = R_GetCurrentTexture(surface->texture);
8637
8638         // just use the first triangle with a valid normal for any decisions
8639         VectorClear(normal);
8640         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8641         {
8642                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8643                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8644                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8645                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8646                 if (VectorLength2(normal) >= 0.001)
8647                         break;
8648         }
8649
8650         VectorCopy(normal, plane.normal);
8651         VectorNormalize(plane.normal);
8652         plane.dist = DotProduct(vert[0], plane.normal);
8653         PlaneClassify(&plane);
8654         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8655         {
8656                 // skip backfaces (except if nocullface is set)
8657                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8658                         return;
8659                 VectorNegate(plane.normal, plane.normal);
8660                 plane.dist *= -1;
8661                 PlaneClassify(&plane);
8662         }
8663
8664
8665         // find a matching plane if there is one
8666         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8667                 if(p->camera_entity == t->camera_entity)
8668                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8669                                 break;
8670         if (planeindex >= r_waterstate.maxwaterplanes)
8671                 return; // nothing we can do, out of planes
8672
8673         // if this triangle does not fit any known plane rendered this frame, add one
8674         if (planeindex >= r_waterstate.numwaterplanes)
8675         {
8676                 // store the new plane
8677                 r_waterstate.numwaterplanes++;
8678                 p->plane = plane;
8679                 // clear materialflags and pvs
8680                 p->materialflags = 0;
8681                 p->pvsvalid = false;
8682                 p->camera_entity = t->camera_entity;
8683                 VectorCopy(surface->mins, p->mins);
8684                 VectorCopy(surface->maxs, p->maxs);
8685         }
8686         else
8687         {
8688                 // merge mins/maxs
8689                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8690                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8691                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8692                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8693                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8694                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8695         }
8696         // merge this surface's materialflags into the waterplane
8697         p->materialflags |= t->currentmaterialflags;
8698         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8699         {
8700                 // merge this surface's PVS into the waterplane
8701                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8702                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8703                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8704                 {
8705                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8706                         p->pvsvalid = true;
8707                 }
8708         }
8709 }
8710
8711 static void R_Water_ProcessPlanes(void)
8712 {
8713         int myscissor[4];
8714         r_refdef_view_t originalview;
8715         r_refdef_view_t myview;
8716         int planeindex;
8717         r_waterstate_waterplane_t *p;
8718         vec3_t visorigin;
8719
8720         originalview = r_refdef.view;
8721
8722         // make sure enough textures are allocated
8723         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8724         {
8725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8726                 {
8727                         if (!p->texture_refraction)
8728                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8729                         if (!p->texture_refraction)
8730                                 goto error;
8731                 }
8732                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8733                 {
8734                         if (!p->texture_camera)
8735                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8736                         if (!p->texture_camera)
8737                                 goto error;
8738                 }
8739
8740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8741                 {
8742                         if (!p->texture_reflection)
8743                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8744                         if (!p->texture_reflection)
8745                                 goto error;
8746                 }
8747         }
8748
8749         // render views
8750         r_refdef.view = originalview;
8751         r_refdef.view.showdebug = false;
8752         r_refdef.view.width = r_waterstate.waterwidth;
8753         r_refdef.view.height = r_waterstate.waterheight;
8754         r_refdef.view.useclipplane = true;
8755         myview = r_refdef.view;
8756         r_waterstate.renderingscene = true;
8757         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8758         {
8759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8760                 {
8761                         r_refdef.view = myview;
8762                         if(r_water_scissormode.integer)
8763                         {
8764                                 R_SetupView(true);
8765                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8766                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8767                         }
8768
8769                         // render reflected scene and copy into texture
8770                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8771                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8772                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8773                         r_refdef.view.clipplane = p->plane;
8774
8775                         // reverse the cullface settings for this render
8776                         r_refdef.view.cullface_front = GL_FRONT;
8777                         r_refdef.view.cullface_back = GL_BACK;
8778                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8779                         {
8780                                 r_refdef.view.usecustompvs = true;
8781                                 if (p->pvsvalid)
8782                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8783                                 else
8784                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8785                         }
8786
8787                         R_ResetViewRendering3D();
8788                         R_ClearScreen(r_refdef.fogenabled);
8789                         if(r_water_scissormode.integer & 2)
8790                                 R_View_UpdateWithScissor(myscissor);
8791                         else
8792                                 R_View_Update();
8793                         if(r_water_scissormode.integer & 1)
8794                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8795                         R_RenderScene();
8796
8797                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8798                 }
8799
8800                 // render the normal view scene and copy into texture
8801                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
8802                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8803                 {
8804                         r_refdef.view = myview;
8805                         if(r_water_scissormode.integer)
8806                         {
8807                                 R_SetupView(true);
8808                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8809                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8810                         }
8811
8812                         r_waterstate.renderingrefraction = true;
8813
8814                         r_refdef.view.clipplane = p->plane;
8815                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8816                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8817
8818                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8819                         {
8820                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8821                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8822                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8823                                 R_RenderView_UpdateViewVectors();
8824                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8825                                 {
8826                                         r_refdef.view.usecustompvs = true;
8827                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8828                                 }
8829                         }
8830
8831                         PlaneClassify(&r_refdef.view.clipplane);
8832
8833                         R_ResetViewRendering3D();
8834                         R_ClearScreen(r_refdef.fogenabled);
8835                         if(r_water_scissormode.integer & 2)
8836                                 R_View_UpdateWithScissor(myscissor);
8837                         else
8838                                 R_View_Update();
8839                         if(r_water_scissormode.integer & 1)
8840                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8841                         R_RenderScene();
8842
8843                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8844                         r_waterstate.renderingrefraction = false;
8845                 }
8846                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8847                 {
8848                         r_refdef.view = myview;
8849
8850                         r_refdef.view.clipplane = p->plane;
8851                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8852                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8853
8854                         r_refdef.view.width = r_waterstate.camerawidth;
8855                         r_refdef.view.height = r_waterstate.cameraheight;
8856                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8857                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8858
8859                         if(p->camera_entity)
8860                         {
8861                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8862                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8863                         }
8864
8865                         // note: all of the view is used for displaying... so
8866                         // there is no use in scissoring
8867
8868                         // reverse the cullface settings for this render
8869                         r_refdef.view.cullface_front = GL_FRONT;
8870                         r_refdef.view.cullface_back = GL_BACK;
8871                         // also reverse the view matrix
8872                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8873                         R_RenderView_UpdateViewVectors();
8874                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8875                         {
8876                                 r_refdef.view.usecustompvs = true;
8877                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8878                         }
8879                         
8880                         // camera needs no clipplane
8881                         r_refdef.view.useclipplane = false;
8882
8883                         PlaneClassify(&r_refdef.view.clipplane);
8884
8885                         R_ResetViewRendering3D();
8886                         R_ClearScreen(r_refdef.fogenabled);
8887                         R_View_Update();
8888                         R_RenderScene();
8889
8890                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8891                         r_waterstate.renderingrefraction = false;
8892                 }
8893
8894         }
8895         r_waterstate.renderingscene = false;
8896         r_refdef.view = originalview;
8897         R_ResetViewRendering3D();
8898         R_ClearScreen(r_refdef.fogenabled);
8899         R_View_Update();
8900         return;
8901 error:
8902         r_refdef.view = originalview;
8903         r_waterstate.renderingscene = false;
8904         Cvar_SetValueQuick(&r_water, 0);
8905         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8906         return;
8907 }
8908
8909 void R_Bloom_StartFrame(void)
8910 {
8911         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8912
8913         switch(vid.renderpath)
8914         {
8915         case RENDERPATH_GL20:
8916         case RENDERPATH_CGGL:
8917         case RENDERPATH_D3D9:
8918         case RENDERPATH_D3D10:
8919         case RENDERPATH_D3D11:
8920                 break;
8921         case RENDERPATH_GL13:
8922         case RENDERPATH_GL11:
8923                 return;
8924         }
8925
8926         // set bloomwidth and bloomheight to the bloom resolution that will be
8927         // used (often less than the screen resolution for faster rendering)
8928         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8929         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8930         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8931         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8932         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8933
8934         // calculate desired texture sizes
8935         if (vid.support.arb_texture_non_power_of_two)
8936         {
8937                 screentexturewidth = r_refdef.view.width;
8938                 screentextureheight = r_refdef.view.height;
8939                 bloomtexturewidth = r_bloomstate.bloomwidth;
8940                 bloomtextureheight = r_bloomstate.bloomheight;
8941         }
8942         else
8943         {
8944                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8945                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8946                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8947                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8948         }
8949
8950         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
8951         {
8952                 Cvar_SetValueQuick(&r_hdr, 0);
8953                 Cvar_SetValueQuick(&r_bloom, 0);
8954                 Cvar_SetValueQuick(&r_motionblur, 0);
8955                 Cvar_SetValueQuick(&r_damageblur, 0);
8956         }
8957
8958         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
8959                 screentexturewidth = screentextureheight = 0;
8960         if (!r_hdr.integer && !r_bloom.integer)
8961                 bloomtexturewidth = bloomtextureheight = 0;
8962
8963         // allocate textures as needed
8964         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8965         {
8966                 if (r_bloomstate.texture_screen)
8967                         R_FreeTexture(r_bloomstate.texture_screen);
8968                 r_bloomstate.texture_screen = NULL;
8969                 r_bloomstate.screentexturewidth = screentexturewidth;
8970                 r_bloomstate.screentextureheight = screentextureheight;
8971                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8972                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8973         }
8974         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8975         {
8976                 if (r_bloomstate.texture_bloom)
8977                         R_FreeTexture(r_bloomstate.texture_bloom);
8978                 r_bloomstate.texture_bloom = NULL;
8979                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8980                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8981                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8982                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8983         }
8984
8985         // when doing a reduced render (HDR) we want to use a smaller area
8986         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8987         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8988         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8989         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8990         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8991
8992         // set up a texcoord array for the full resolution screen image
8993         // (we have to keep this around to copy back during final render)
8994         r_bloomstate.screentexcoord2f[0] = 0;
8995         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8996         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8997         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8998         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8999         r_bloomstate.screentexcoord2f[5] = 0;
9000         r_bloomstate.screentexcoord2f[6] = 0;
9001         r_bloomstate.screentexcoord2f[7] = 0;
9002
9003         // set up a texcoord array for the reduced resolution bloom image
9004         // (which will be additive blended over the screen image)
9005         r_bloomstate.bloomtexcoord2f[0] = 0;
9006         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9007         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9008         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9009         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9010         r_bloomstate.bloomtexcoord2f[5] = 0;
9011         r_bloomstate.bloomtexcoord2f[6] = 0;
9012         r_bloomstate.bloomtexcoord2f[7] = 0;
9013
9014         switch(vid.renderpath)
9015         {
9016         case RENDERPATH_GL11:
9017         case RENDERPATH_GL13:
9018         case RENDERPATH_GL20:
9019         case RENDERPATH_CGGL:
9020                 break;
9021         case RENDERPATH_D3D9:
9022         case RENDERPATH_D3D10:
9023         case RENDERPATH_D3D11:
9024                 {
9025                         int i;
9026                         for (i = 0;i < 4;i++)
9027                         {
9028                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9029                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9030                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9031                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9032                         }
9033                 }
9034                 break;
9035         }
9036
9037         if (r_hdr.integer || r_bloom.integer)
9038         {
9039                 r_bloomstate.enabled = true;
9040                 r_bloomstate.hdr = r_hdr.integer != 0;
9041         }
9042
9043         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
9044 }
9045
9046 void R_Bloom_CopyBloomTexture(float colorscale)
9047 {
9048         r_refdef.stats.bloom++;
9049
9050         // scale down screen texture to the bloom texture size
9051         CHECKGLERROR
9052         R_SetViewport(&r_bloomstate.viewport);
9053         GL_BlendFunc(GL_ONE, GL_ZERO);
9054         GL_Color(colorscale, colorscale, colorscale, 1);
9055         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9056         switch(vid.renderpath)
9057         {
9058         case RENDERPATH_GL11:
9059         case RENDERPATH_GL13:
9060         case RENDERPATH_GL20:
9061         case RENDERPATH_CGGL:
9062                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9063                 break;
9064         case RENDERPATH_D3D9:
9065         case RENDERPATH_D3D10:
9066         case RENDERPATH_D3D11:
9067                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9068                 break;
9069         }
9070         // TODO: do boxfilter scale-down in shader?
9071         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9072         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9073         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9074
9075         // we now have a bloom image in the framebuffer
9076         // copy it into the bloom image texture for later processing
9077         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9078         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9079 }
9080
9081 void R_Bloom_CopyHDRTexture(void)
9082 {
9083         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
9084         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9085 }
9086
9087 void R_Bloom_MakeTexture(void)
9088 {
9089         int x, range, dir;
9090         float xoffset, yoffset, r, brighten;
9091
9092         r_refdef.stats.bloom++;
9093
9094         R_ResetViewRendering2D();
9095
9096         // we have a bloom image in the framebuffer
9097         CHECKGLERROR
9098         R_SetViewport(&r_bloomstate.viewport);
9099
9100         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9101         {
9102                 x *= 2;
9103                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9104                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9105                 GL_Color(r,r,r,1);
9106                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9107                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9108                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9109                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9110
9111                 // copy the vertically blurred bloom view to a texture
9112                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9113                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9114         }
9115
9116         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9117         brighten = r_bloom_brighten.value;
9118         if (r_hdr.integer)
9119                 brighten *= r_hdr_range.value;
9120         brighten = sqrt(brighten);
9121         if(range >= 1)
9122                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9123         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9124
9125         for (dir = 0;dir < 2;dir++)
9126         {
9127                 // blend on at multiple vertical offsets to achieve a vertical blur
9128                 // TODO: do offset blends using GLSL
9129                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9130                 GL_BlendFunc(GL_ONE, GL_ZERO);
9131                 for (x = -range;x <= range;x++)
9132                 {
9133                         if (!dir){xoffset = 0;yoffset = x;}
9134                         else {xoffset = x;yoffset = 0;}
9135                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9136                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9137                         // compute a texcoord array with the specified x and y offset
9138                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9139                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9140                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9141                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9142                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9143                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9144                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9145                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9146                         // this r value looks like a 'dot' particle, fading sharply to
9147                         // black at the edges
9148                         // (probably not realistic but looks good enough)
9149                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9150                         //r = brighten/(range*2+1);
9151                         r = brighten / (range * 2 + 1);
9152                         if(range >= 1)
9153                                 r *= (1 - x*x/(float)(range*range));
9154                         GL_Color(r, r, r, 1);
9155                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9156                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9157                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9158                         GL_BlendFunc(GL_ONE, GL_ONE);
9159                 }
9160
9161                 // copy the vertically blurred bloom view to a texture
9162                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
9163                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9164         }
9165 }
9166
9167 void R_HDR_RenderBloomTexture(void)
9168 {
9169         int oldwidth, oldheight;
9170         float oldcolorscale;
9171         int oldwaterstate;
9172
9173         oldwaterstate = r_waterstate.enabled;
9174         oldcolorscale = r_refdef.view.colorscale;
9175         oldwidth = r_refdef.view.width;
9176         oldheight = r_refdef.view.height;
9177         r_refdef.view.width = r_bloomstate.bloomwidth;
9178         r_refdef.view.height = r_bloomstate.bloomheight;
9179
9180         if(r_hdr.integer < 2)
9181                 r_waterstate.enabled = false;
9182
9183         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9184         // TODO: add exposure compensation features
9185         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9186
9187         r_refdef.view.showdebug = false;
9188         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9189
9190         R_ResetViewRendering3D();
9191
9192         R_ClearScreen(r_refdef.fogenabled);
9193         if (r_timereport_active)
9194                 R_TimeReport("HDRclear");
9195
9196         R_View_Update();
9197         if (r_timereport_active)
9198                 R_TimeReport("visibility");
9199
9200         // only do secondary renders with HDR if r_hdr is 2 or higher
9201         r_waterstate.numwaterplanes = 0;
9202         if (r_waterstate.enabled)
9203                 R_RenderWaterPlanes();
9204
9205         r_refdef.view.showdebug = true;
9206         R_RenderScene();
9207         r_waterstate.numwaterplanes = 0;
9208
9209         R_ResetViewRendering2D();
9210
9211         R_Bloom_CopyHDRTexture();
9212         R_Bloom_MakeTexture();
9213
9214         // restore the view settings
9215         r_waterstate.enabled = oldwaterstate;
9216         r_refdef.view.width = oldwidth;
9217         r_refdef.view.height = oldheight;
9218         r_refdef.view.colorscale = oldcolorscale;
9219
9220         R_ResetViewRendering3D();
9221
9222         R_ClearScreen(r_refdef.fogenabled);
9223         if (r_timereport_active)
9224                 R_TimeReport("viewclear");
9225 }
9226
9227 static void R_BlendView(void)
9228 {
9229         unsigned int permutation;
9230         float uservecs[4][4];
9231
9232         switch (vid.renderpath)
9233         {
9234         case RENDERPATH_GL20:
9235         case RENDERPATH_CGGL:
9236         case RENDERPATH_D3D9:
9237         case RENDERPATH_D3D10:
9238         case RENDERPATH_D3D11:
9239                 permutation =
9240                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9241                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9242                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9243                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9244                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9245
9246                 if (r_bloomstate.texture_screen)
9247                 {
9248                         // make sure the buffer is available
9249                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9250
9251                         R_ResetViewRendering2D();
9252
9253                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9254                         {
9255                                 // declare variables
9256                                 float speed;
9257                                 static float avgspeed;
9258
9259                                 speed = VectorLength(cl.movement_velocity);
9260
9261                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9262                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9263
9264                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9265                                 speed = bound(0, speed, 1);
9266                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9267
9268                                 // calculate values into a standard alpha
9269                                 cl.motionbluralpha = 1 - exp(-
9270                                                 (
9271                                                  (r_motionblur.value * speed / 80)
9272                                                  +
9273                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9274                                                 )
9275                                                 /
9276                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9277                                            );
9278
9279                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9280                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9281                                 // apply the blur
9282                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9283                                 {
9284                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9285                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9286                                         switch(vid.renderpath)
9287                                         {
9288                                         case RENDERPATH_GL11:
9289                                         case RENDERPATH_GL13:
9290                                         case RENDERPATH_GL20:
9291                                         case RENDERPATH_CGGL:
9292                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9293                                                 break;
9294                                         case RENDERPATH_D3D9:
9295                                         case RENDERPATH_D3D10:
9296                                         case RENDERPATH_D3D11:
9297                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9298                                                 break;
9299                                         }
9300                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9301                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9302                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9303                                 }
9304                         }
9305
9306                         // copy view into the screen texture
9307                         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);
9308                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9309                 }
9310                 else if (!r_bloomstate.texture_bloom)
9311                 {
9312                         // we may still have to do view tint...
9313                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9314                         {
9315                                 // apply a color tint to the whole view
9316                                 R_ResetViewRendering2D();
9317                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9318                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9319                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9320                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9321                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9322                         }
9323                         break; // no screen processing, no bloom, skip it
9324                 }
9325
9326                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9327                 {
9328                         // render simple bloom effect
9329                         // copy the screen and shrink it and darken it for the bloom process
9330                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9331                         // make the bloom texture
9332                         R_Bloom_MakeTexture();
9333                 }
9334
9335 #if _MSC_VER >= 1400
9336 #define sscanf sscanf_s
9337 #endif
9338                 memset(uservecs, 0, sizeof(uservecs));
9339                 if (r_glsl_postprocess_uservec1_enable.integer)
9340                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9341                 if (r_glsl_postprocess_uservec2_enable.integer)
9342                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9343                 if (r_glsl_postprocess_uservec3_enable.integer)
9344                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9345                 if (r_glsl_postprocess_uservec4_enable.integer)
9346                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9347
9348                 R_ResetViewRendering2D();
9349                 GL_Color(1, 1, 1, 1);
9350                 GL_BlendFunc(GL_ONE, GL_ZERO);
9351
9352                 switch(vid.renderpath)
9353                 {
9354                 case RENDERPATH_GL20:
9355                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9356                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9357                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9358                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9359                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9360                         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]);
9361                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9362                         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]);
9363                         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]);
9364                         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]);
9365                         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]);
9366                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9367                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9368                         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);
9369                         break;
9370                 case RENDERPATH_CGGL:
9371 #ifdef SUPPORTCG
9372                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9373                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9374                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9375                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9376                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9377                         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
9378                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9379                         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
9380                         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
9381                         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
9382                         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
9383                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9384                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9385                         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);
9386 #endif
9387                         break;
9388                 case RENDERPATH_D3D9:
9389 #ifdef SUPPORTD3D
9390                         // 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...
9391                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9392                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9393                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9394                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9395                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9396                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9397                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9398                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9399                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9400                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9401                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9402                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9403                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9404                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9405 #endif
9406                         break;
9407                 case RENDERPATH_D3D10:
9408                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9409                         break;
9410                 case RENDERPATH_D3D11:
9411                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9412                         break;
9413                 default:
9414                         break;
9415                 }
9416                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9417                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9418                 break;
9419         case RENDERPATH_GL13:
9420         case RENDERPATH_GL11:
9421                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9422                 {
9423                         // apply a color tint to the whole view
9424                         R_ResetViewRendering2D();
9425                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9426                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9427                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9428                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9429                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9430                 }
9431                 break;
9432         }
9433 }
9434
9435 matrix4x4_t r_waterscrollmatrix;
9436
9437 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9438 {
9439         if (r_refdef.fog_density)
9440         {
9441                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9442                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9443                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9444
9445                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9446                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9447                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9448                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9449
9450                 {
9451                         vec3_t fogvec;
9452                         VectorCopy(r_refdef.fogcolor, fogvec);
9453                         //   color.rgb *= ContrastBoost * SceneBrightness;
9454                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9455                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9456                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9457                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9458                 }
9459         }
9460 }
9461
9462 void R_UpdateVariables(void)
9463 {
9464         R_Textures_Frame();
9465
9466         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9467
9468         r_refdef.farclip = r_farclip_base.value;
9469         if (r_refdef.scene.worldmodel)
9470                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9471         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9472
9473         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9474                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9475         r_refdef.polygonfactor = 0;
9476         r_refdef.polygonoffset = 0;
9477         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9478         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9479
9480         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9481         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9482         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9483         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9484         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9485         if (FAKELIGHT_ENABLED)
9486         {
9487                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9488         }
9489         if (r_showsurfaces.integer)
9490         {
9491                 r_refdef.scene.rtworld = false;
9492                 r_refdef.scene.rtworldshadows = false;
9493                 r_refdef.scene.rtdlight = false;
9494                 r_refdef.scene.rtdlightshadows = false;
9495                 r_refdef.lightmapintensity = 0;
9496         }
9497
9498         if (gamemode == GAME_NEHAHRA)
9499         {
9500                 if (gl_fogenable.integer)
9501                 {
9502                         r_refdef.oldgl_fogenable = true;
9503                         r_refdef.fog_density = gl_fogdensity.value;
9504                         r_refdef.fog_red = gl_fogred.value;
9505                         r_refdef.fog_green = gl_foggreen.value;
9506                         r_refdef.fog_blue = gl_fogblue.value;
9507                         r_refdef.fog_alpha = 1;
9508                         r_refdef.fog_start = 0;
9509                         r_refdef.fog_end = gl_skyclip.value;
9510                         r_refdef.fog_height = 1<<30;
9511                         r_refdef.fog_fadedepth = 128;
9512                 }
9513                 else if (r_refdef.oldgl_fogenable)
9514                 {
9515                         r_refdef.oldgl_fogenable = false;
9516                         r_refdef.fog_density = 0;
9517                         r_refdef.fog_red = 0;
9518                         r_refdef.fog_green = 0;
9519                         r_refdef.fog_blue = 0;
9520                         r_refdef.fog_alpha = 0;
9521                         r_refdef.fog_start = 0;
9522                         r_refdef.fog_end = 0;
9523                         r_refdef.fog_height = 1<<30;
9524                         r_refdef.fog_fadedepth = 128;
9525                 }
9526         }
9527
9528         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9529         r_refdef.fog_start = max(0, r_refdef.fog_start);
9530         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9531
9532         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9533
9534         if (r_refdef.fog_density && r_drawfog.integer)
9535         {
9536                 r_refdef.fogenabled = true;
9537                 // this is the point where the fog reaches 0.9986 alpha, which we
9538                 // consider a good enough cutoff point for the texture
9539                 // (0.9986 * 256 == 255.6)
9540                 if (r_fog_exp2.integer)
9541                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9542                 else
9543                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9544                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9545                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9546                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9547                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9548                         R_BuildFogHeightTexture();
9549                 // fog color was already set
9550                 // update the fog texture
9551                 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)
9552                         R_BuildFogTexture();
9553                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9554                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9555         }
9556         else
9557                 r_refdef.fogenabled = false;
9558
9559         switch(vid.renderpath)
9560         {
9561         case RENDERPATH_GL20:
9562         case RENDERPATH_CGGL:
9563         case RENDERPATH_D3D9:
9564         case RENDERPATH_D3D10:
9565         case RENDERPATH_D3D11:
9566                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9567                 {
9568                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9569                         {
9570                                 // build GLSL gamma texture
9571 #define RAMPWIDTH 256
9572                                 unsigned short ramp[RAMPWIDTH * 3];
9573                                 unsigned char rampbgr[RAMPWIDTH][4];
9574                                 int i;
9575
9576                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9577
9578                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9579                                 for(i = 0; i < RAMPWIDTH; ++i)
9580                                 {
9581                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9582                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9583                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9584                                         rampbgr[i][3] = 0;
9585                                 }
9586                                 if (r_texture_gammaramps)
9587                                 {
9588                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9589                                 }
9590                                 else
9591                                 {
9592                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9593                                 }
9594                         }
9595                 }
9596                 else
9597                 {
9598                         // remove GLSL gamma texture
9599                 }
9600                 break;
9601         case RENDERPATH_GL13:
9602         case RENDERPATH_GL11:
9603                 break;
9604         }
9605 }
9606
9607 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9608 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9609 /*
9610 ================
9611 R_SelectScene
9612 ================
9613 */
9614 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9615         if( scenetype != r_currentscenetype ) {
9616                 // store the old scenetype
9617                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9618                 r_currentscenetype = scenetype;
9619                 // move in the new scene
9620                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9621         }
9622 }
9623
9624 /*
9625 ================
9626 R_GetScenePointer
9627 ================
9628 */
9629 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9630 {
9631         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9632         if( scenetype == r_currentscenetype ) {
9633                 return &r_refdef.scene;
9634         } else {
9635                 return &r_scenes_store[ scenetype ];
9636         }
9637 }
9638
9639 /*
9640 ================
9641 R_RenderView
9642 ================
9643 */
9644 void R_RenderView(void)
9645 {
9646         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9647         if (r_timereport_active)
9648                 R_TimeReport("start");
9649         r_textureframe++; // used only by R_GetCurrentTexture
9650         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9651
9652         if(R_CompileShader_CheckStaticParms())
9653                 R_GLSL_Restart_f();
9654
9655         if (!r_drawentities.integer)
9656                 r_refdef.scene.numentities = 0;
9657
9658         R_AnimCache_ClearCache();
9659         R_FrameData_NewFrame();
9660
9661         /* adjust for stereo display */
9662         if(R_Stereo_Active())
9663         {
9664                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
9665                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9666         }
9667
9668         if (r_refdef.view.isoverlay)
9669         {
9670                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9671                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9672                 R_TimeReport("depthclear");
9673
9674                 r_refdef.view.showdebug = false;
9675
9676                 r_waterstate.enabled = false;
9677                 r_waterstate.numwaterplanes = 0;
9678
9679                 R_RenderScene();
9680
9681                 r_refdef.view.matrix = originalmatrix;
9682
9683                 CHECKGLERROR
9684                 return;
9685         }
9686
9687         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9688         {
9689                 r_refdef.view.matrix = originalmatrix;
9690                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9691         }
9692
9693         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9694
9695         R_RenderView_UpdateViewVectors();
9696
9697         R_Shadow_UpdateWorldLightSelection();
9698
9699         R_Bloom_StartFrame();
9700         R_Water_StartFrame();
9701
9702         CHECKGLERROR
9703         if (r_timereport_active)
9704                 R_TimeReport("viewsetup");
9705
9706         R_ResetViewRendering3D();
9707
9708         if (r_refdef.view.clear || r_refdef.fogenabled)
9709         {
9710                 R_ClearScreen(r_refdef.fogenabled);
9711                 if (r_timereport_active)
9712                         R_TimeReport("viewclear");
9713         }
9714         r_refdef.view.clear = true;
9715
9716         // this produces a bloom texture to be used in R_BlendView() later
9717         if (r_hdr.integer && r_bloomstate.bloomwidth)
9718         {
9719                 R_HDR_RenderBloomTexture();
9720                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9721                 r_textureframe++; // used only by R_GetCurrentTexture
9722         }
9723
9724         r_refdef.view.showdebug = true;
9725
9726         R_View_Update();
9727         if (r_timereport_active)
9728                 R_TimeReport("visibility");
9729
9730         r_waterstate.numwaterplanes = 0;
9731         if (r_waterstate.enabled)
9732                 R_RenderWaterPlanes();
9733
9734         R_RenderScene();
9735         r_waterstate.numwaterplanes = 0;
9736
9737         R_BlendView();
9738         if (r_timereport_active)
9739                 R_TimeReport("blendview");
9740
9741         GL_Scissor(0, 0, vid.width, vid.height);
9742         GL_ScissorTest(false);
9743
9744         r_refdef.view.matrix = originalmatrix;
9745
9746         CHECKGLERROR
9747 }
9748
9749 void R_RenderWaterPlanes(void)
9750 {
9751         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9752         {
9753                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9754                 if (r_timereport_active)
9755                         R_TimeReport("waterworld");
9756         }
9757
9758         // don't let sound skip if going slow
9759         if (r_refdef.scene.extraupdate)
9760                 S_ExtraUpdate ();
9761
9762         R_DrawModelsAddWaterPlanes();
9763         if (r_timereport_active)
9764                 R_TimeReport("watermodels");
9765
9766         if (r_waterstate.numwaterplanes)
9767         {
9768                 R_Water_ProcessPlanes();
9769                 if (r_timereport_active)
9770                         R_TimeReport("waterscenes");
9771         }
9772 }
9773
9774 extern void R_DrawLightningBeams (void);
9775 extern void VM_CL_AddPolygonsToMeshQueue (void);
9776 extern void R_DrawPortals (void);
9777 extern cvar_t cl_locs_show;
9778 static void R_DrawLocs(void);
9779 static void R_DrawEntityBBoxes(void);
9780 static void R_DrawModelDecals(void);
9781 extern void R_DrawModelShadows(void);
9782 extern void R_DrawModelShadowMaps(void);
9783 extern cvar_t cl_decals_newsystem;
9784 extern qboolean r_shadow_usingdeferredprepass;
9785 void R_RenderScene(void)
9786 {
9787         qboolean shadowmapping = false;
9788
9789         if (r_timereport_active)
9790                 R_TimeReport("beginscene");
9791
9792         r_refdef.stats.renders++;
9793
9794         R_UpdateFogColor();
9795
9796         // don't let sound skip if going slow
9797         if (r_refdef.scene.extraupdate)
9798                 S_ExtraUpdate ();
9799
9800         R_MeshQueue_BeginScene();
9801
9802         R_SkyStartFrame();
9803
9804         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);
9805
9806         if (r_timereport_active)
9807                 R_TimeReport("skystartframe");
9808
9809         if (cl.csqc_vidvars.drawworld)
9810         {
9811                 // don't let sound skip if going slow
9812                 if (r_refdef.scene.extraupdate)
9813                         S_ExtraUpdate ();
9814
9815                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9816                 {
9817                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9818                         if (r_timereport_active)
9819                                 R_TimeReport("worldsky");
9820                 }
9821
9822                 if (R_DrawBrushModelsSky() && r_timereport_active)
9823                         R_TimeReport("bmodelsky");
9824
9825                 if (skyrendermasked && skyrenderlater)
9826                 {
9827                         // we have to force off the water clipping plane while rendering sky
9828                         R_SetupView(false);
9829                         R_Sky();
9830                         R_SetupView(true);
9831                         if (r_timereport_active)
9832                                 R_TimeReport("sky");
9833                 }
9834         }
9835
9836         R_AnimCache_CacheVisibleEntities();
9837         if (r_timereport_active)
9838                 R_TimeReport("animation");
9839
9840         R_Shadow_PrepareLights();
9841         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9842                 R_Shadow_PrepareModelShadows();
9843         if (r_timereport_active)
9844                 R_TimeReport("preparelights");
9845
9846         if (R_Shadow_ShadowMappingEnabled())
9847                 shadowmapping = true;
9848
9849         if (r_shadow_usingdeferredprepass)
9850                 R_Shadow_DrawPrepass();
9851
9852         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9853         {
9854                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9855                 if (r_timereport_active)
9856                         R_TimeReport("worlddepth");
9857         }
9858         if (r_depthfirst.integer >= 2)
9859         {
9860                 R_DrawModelsDepth();
9861                 if (r_timereport_active)
9862                         R_TimeReport("modeldepth");
9863         }
9864
9865         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9866         {
9867                 R_DrawModelShadowMaps();
9868                 R_ResetViewRendering3D();
9869                 // don't let sound skip if going slow
9870                 if (r_refdef.scene.extraupdate)
9871                         S_ExtraUpdate ();
9872         }
9873
9874         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9875         {
9876                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9877                 if (r_timereport_active)
9878                         R_TimeReport("world");
9879         }
9880
9881         // don't let sound skip if going slow
9882         if (r_refdef.scene.extraupdate)
9883                 S_ExtraUpdate ();
9884
9885         R_DrawModels();
9886         if (r_timereport_active)
9887                 R_TimeReport("models");
9888
9889         // don't let sound skip if going slow
9890         if (r_refdef.scene.extraupdate)
9891                 S_ExtraUpdate ();
9892
9893         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9894         {
9895                 R_DrawModelShadows();
9896                 R_ResetViewRendering3D();
9897                 // don't let sound skip if going slow
9898                 if (r_refdef.scene.extraupdate)
9899                         S_ExtraUpdate ();
9900         }
9901
9902         if (!r_shadow_usingdeferredprepass)
9903         {
9904                 R_Shadow_DrawLights();
9905                 if (r_timereport_active)
9906                         R_TimeReport("rtlights");
9907         }
9908
9909         // don't let sound skip if going slow
9910         if (r_refdef.scene.extraupdate)
9911                 S_ExtraUpdate ();
9912
9913         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9914         {
9915                 R_DrawModelShadows();
9916                 R_ResetViewRendering3D();
9917                 // don't let sound skip if going slow
9918                 if (r_refdef.scene.extraupdate)
9919                         S_ExtraUpdate ();
9920         }
9921
9922         if (cl.csqc_vidvars.drawworld)
9923         {
9924                 if (cl_decals_newsystem.integer)
9925                 {
9926                         R_DrawModelDecals();
9927                         if (r_timereport_active)
9928                                 R_TimeReport("modeldecals");
9929                 }
9930                 else
9931                 {
9932                         R_DrawDecals();
9933                         if (r_timereport_active)
9934                                 R_TimeReport("decals");
9935                 }
9936
9937                 R_DrawParticles();
9938                 if (r_timereport_active)
9939                         R_TimeReport("particles");
9940
9941                 R_DrawExplosions();
9942                 if (r_timereport_active)
9943                         R_TimeReport("explosions");
9944
9945                 R_DrawLightningBeams();
9946                 if (r_timereport_active)
9947                         R_TimeReport("lightning");
9948         }
9949
9950         VM_CL_AddPolygonsToMeshQueue();
9951
9952         if (r_refdef.view.showdebug)
9953         {
9954                 if (cl_locs_show.integer)
9955                 {
9956                         R_DrawLocs();
9957                         if (r_timereport_active)
9958                                 R_TimeReport("showlocs");
9959                 }
9960
9961                 if (r_drawportals.integer)
9962                 {
9963                         R_DrawPortals();
9964                         if (r_timereport_active)
9965                                 R_TimeReport("portals");
9966                 }
9967
9968                 if (r_showbboxes.value > 0)
9969                 {
9970                         R_DrawEntityBBoxes();
9971                         if (r_timereport_active)
9972                                 R_TimeReport("bboxes");
9973                 }
9974         }
9975
9976         R_MeshQueue_RenderTransparent();
9977         if (r_timereport_active)
9978                 R_TimeReport("drawtrans");
9979
9980         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))
9981         {
9982                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9983                 if (r_timereport_active)
9984                         R_TimeReport("worlddebug");
9985                 R_DrawModelsDebug();
9986                 if (r_timereport_active)
9987                         R_TimeReport("modeldebug");
9988         }
9989
9990         if (cl.csqc_vidvars.drawworld)
9991         {
9992                 R_Shadow_DrawCoronas();
9993                 if (r_timereport_active)
9994                         R_TimeReport("coronas");
9995         }
9996
9997 #if 0
9998         {
9999                 GL_DepthTest(false);
10000                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10001                 GL_Color(1, 1, 1, 1);
10002                 qglBegin(GL_POLYGON);
10003                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10004                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10005                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10006                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10007                 qglEnd();
10008                 qglBegin(GL_POLYGON);
10009                 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]);
10010                 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]);
10011                 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]);
10012                 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]);
10013                 qglEnd();
10014                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10015         }
10016 #endif
10017
10018         // don't let sound skip if going slow
10019         if (r_refdef.scene.extraupdate)
10020                 S_ExtraUpdate ();
10021
10022         R_ResetViewRendering2D();
10023 }
10024
10025 static const unsigned short bboxelements[36] =
10026 {
10027         5, 1, 3, 5, 3, 7,
10028         6, 2, 0, 6, 0, 4,
10029         7, 3, 2, 7, 2, 6,
10030         4, 0, 1, 4, 1, 5,
10031         4, 5, 7, 4, 7, 6,
10032         1, 0, 2, 1, 2, 3,
10033 };
10034
10035 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10036 {
10037         int i;
10038         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10039
10040         RSurf_ActiveWorldEntity();
10041
10042         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10043         GL_DepthMask(false);
10044         GL_DepthRange(0, 1);
10045         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10046 //      R_Mesh_ResetTextureState();
10047
10048         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10049         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10050         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10051         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10052         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10053         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10054         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10055         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10056         R_FillColors(color4f, 8, cr, cg, cb, ca);
10057         if (r_refdef.fogenabled)
10058         {
10059                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10060                 {
10061                         f1 = RSurf_FogVertex(v);
10062                         f2 = 1 - f1;
10063                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10064                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10065                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10066                 }
10067         }
10068         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10069         R_Mesh_ResetTextureState();
10070         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10071         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10072 }
10073
10074 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10075 {
10076         int i;
10077         float color[4];
10078         prvm_edict_t *edict;
10079         prvm_prog_t *prog_save = prog;
10080
10081         // this function draws bounding boxes of server entities
10082         if (!sv.active)
10083                 return;
10084
10085         GL_CullFace(GL_NONE);
10086         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10087
10088         prog = 0;
10089         SV_VM_Begin();
10090         for (i = 0;i < numsurfaces;i++)
10091         {
10092                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10093                 switch ((int)edict->fields.server->solid)
10094                 {
10095                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10096                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10097                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10098                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10099                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10100                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10101                 }
10102                 color[3] *= r_showbboxes.value;
10103                 color[3] = bound(0, color[3], 1);
10104                 GL_DepthTest(!r_showdisabledepthtest.integer);
10105                 GL_CullFace(r_refdef.view.cullface_front);
10106                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10107         }
10108         SV_VM_End();
10109         prog = prog_save;
10110 }
10111
10112 static void R_DrawEntityBBoxes(void)
10113 {
10114         int i;
10115         prvm_edict_t *edict;
10116         vec3_t center;
10117         prvm_prog_t *prog_save = prog;
10118
10119         // this function draws bounding boxes of server entities
10120         if (!sv.active)
10121                 return;
10122
10123         prog = 0;
10124         SV_VM_Begin();
10125         for (i = 0;i < prog->num_edicts;i++)
10126         {
10127                 edict = PRVM_EDICT_NUM(i);
10128                 if (edict->priv.server->free)
10129                         continue;
10130                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10131                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10132                         continue;
10133                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10134                         continue;
10135                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10136                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10137         }
10138         SV_VM_End();
10139         prog = prog_save;
10140 }
10141
10142 static const int nomodelelement3i[24] =
10143 {
10144         5, 2, 0,
10145         5, 1, 2,
10146         5, 0, 3,
10147         5, 3, 1,
10148         0, 2, 4,
10149         2, 1, 4,
10150         3, 0, 4,
10151         1, 3, 4
10152 };
10153
10154 static const unsigned short nomodelelement3s[24] =
10155 {
10156         5, 2, 0,
10157         5, 1, 2,
10158         5, 0, 3,
10159         5, 3, 1,
10160         0, 2, 4,
10161         2, 1, 4,
10162         3, 0, 4,
10163         1, 3, 4
10164 };
10165
10166 static const float nomodelvertex3f[6*3] =
10167 {
10168         -16,   0,   0,
10169          16,   0,   0,
10170           0, -16,   0,
10171           0,  16,   0,
10172           0,   0, -16,
10173           0,   0,  16
10174 };
10175
10176 static const float nomodelcolor4f[6*4] =
10177 {
10178         0.0f, 0.0f, 0.5f, 1.0f,
10179         0.0f, 0.0f, 0.5f, 1.0f,
10180         0.0f, 0.5f, 0.0f, 1.0f,
10181         0.0f, 0.5f, 0.0f, 1.0f,
10182         0.5f, 0.0f, 0.0f, 1.0f,
10183         0.5f, 0.0f, 0.0f, 1.0f
10184 };
10185
10186 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10187 {
10188         int i;
10189         float f1, f2, *c;
10190         float color4f[6*4];
10191
10192         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);
10193
10194         // this is only called once per entity so numsurfaces is always 1, and
10195         // surfacelist is always {0}, so this code does not handle batches
10196
10197         if (rsurface.ent_flags & RENDER_ADDITIVE)
10198         {
10199                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10200                 GL_DepthMask(false);
10201         }
10202         else if (rsurface.colormod[3] < 1)
10203         {
10204                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10205                 GL_DepthMask(false);
10206         }
10207         else
10208         {
10209                 GL_BlendFunc(GL_ONE, GL_ZERO);
10210                 GL_DepthMask(true);
10211         }
10212         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10213         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10214         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10215         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10216         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10217         for (i = 0, c = color4f;i < 6;i++, c += 4)
10218         {
10219                 c[0] *= rsurface.colormod[0];
10220                 c[1] *= rsurface.colormod[1];
10221                 c[2] *= rsurface.colormod[2];
10222                 c[3] *= rsurface.colormod[3];
10223         }
10224         if (r_refdef.fogenabled)
10225         {
10226                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10227                 {
10228                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10229                         f2 = 1 - f1;
10230                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10231                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10232                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10233                 }
10234         }
10235 //      R_Mesh_ResetTextureState();
10236         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10237         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10238         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10239 }
10240
10241 void R_DrawNoModel(entity_render_t *ent)
10242 {
10243         vec3_t org;
10244         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10245         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10246                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10247         else
10248                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10249 }
10250
10251 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10252 {
10253         vec3_t right1, right2, diff, normal;
10254
10255         VectorSubtract (org2, org1, normal);
10256
10257         // calculate 'right' vector for start
10258         VectorSubtract (r_refdef.view.origin, org1, diff);
10259         CrossProduct (normal, diff, right1);
10260         VectorNormalize (right1);
10261
10262         // calculate 'right' vector for end
10263         VectorSubtract (r_refdef.view.origin, org2, diff);
10264         CrossProduct (normal, diff, right2);
10265         VectorNormalize (right2);
10266
10267         vert[ 0] = org1[0] + width * right1[0];
10268         vert[ 1] = org1[1] + width * right1[1];
10269         vert[ 2] = org1[2] + width * right1[2];
10270         vert[ 3] = org1[0] - width * right1[0];
10271         vert[ 4] = org1[1] - width * right1[1];
10272         vert[ 5] = org1[2] - width * right1[2];
10273         vert[ 6] = org2[0] - width * right2[0];
10274         vert[ 7] = org2[1] - width * right2[1];
10275         vert[ 8] = org2[2] - width * right2[2];
10276         vert[ 9] = org2[0] + width * right2[0];
10277         vert[10] = org2[1] + width * right2[1];
10278         vert[11] = org2[2] + width * right2[2];
10279 }
10280
10281 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)
10282 {
10283         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10284         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10285         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10286         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10287         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10288         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10289         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10290         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10291         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10292         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10293         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10294         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10295 }
10296
10297 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10298 {
10299         int i;
10300         float *vertex3f;
10301         float v[3];
10302         VectorSet(v, x, y, z);
10303         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10304                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10305                         break;
10306         if (i == mesh->numvertices)
10307         {
10308                 if (mesh->numvertices < mesh->maxvertices)
10309                 {
10310                         VectorCopy(v, vertex3f);
10311                         mesh->numvertices++;
10312                 }
10313                 return mesh->numvertices;
10314         }
10315         else
10316                 return i;
10317 }
10318
10319 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10320 {
10321         int i;
10322         int *e, element[3];
10323         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10324         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10325         e = mesh->element3i + mesh->numtriangles * 3;
10326         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10327         {
10328                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10329                 if (mesh->numtriangles < mesh->maxtriangles)
10330                 {
10331                         *e++ = element[0];
10332                         *e++ = element[1];
10333                         *e++ = element[2];
10334                         mesh->numtriangles++;
10335                 }
10336                 element[1] = element[2];
10337         }
10338 }
10339
10340 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10341 {
10342         int i;
10343         int *e, element[3];
10344         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10345         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10346         e = mesh->element3i + mesh->numtriangles * 3;
10347         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10348         {
10349                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10350                 if (mesh->numtriangles < mesh->maxtriangles)
10351                 {
10352                         *e++ = element[0];
10353                         *e++ = element[1];
10354                         *e++ = element[2];
10355                         mesh->numtriangles++;
10356                 }
10357                 element[1] = element[2];
10358         }
10359 }
10360
10361 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10362 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10363 {
10364         int planenum, planenum2;
10365         int w;
10366         int tempnumpoints;
10367         mplane_t *plane, *plane2;
10368         double maxdist;
10369         double temppoints[2][256*3];
10370         // figure out how large a bounding box we need to properly compute this brush
10371         maxdist = 0;
10372         for (w = 0;w < numplanes;w++)
10373                 maxdist = max(maxdist, fabs(planes[w].dist));
10374         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10375         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10376         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10377         {
10378                 w = 0;
10379                 tempnumpoints = 4;
10380                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10381                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10382                 {
10383                         if (planenum2 == planenum)
10384                                 continue;
10385                         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);
10386                         w = !w;
10387                 }
10388                 if (tempnumpoints < 3)
10389                         continue;
10390                 // generate elements forming a triangle fan for this polygon
10391                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10392         }
10393 }
10394
10395 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)
10396 {
10397         texturelayer_t *layer;
10398         layer = t->currentlayers + t->currentnumlayers++;
10399         layer->type = type;
10400         layer->depthmask = depthmask;
10401         layer->blendfunc1 = blendfunc1;
10402         layer->blendfunc2 = blendfunc2;
10403         layer->texture = texture;
10404         layer->texmatrix = *matrix;
10405         layer->color[0] = r;
10406         layer->color[1] = g;
10407         layer->color[2] = b;
10408         layer->color[3] = a;
10409 }
10410
10411 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10412 {
10413         if(parms[0] == 0 && parms[1] == 0)
10414                 return false;
10415         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10416                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10417                         return false;
10418         return true;
10419 }
10420
10421 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10422 {
10423         double index, f;
10424         index = parms[2] + r_refdef.scene.time * parms[3];
10425         index -= floor(index);
10426         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10427         {
10428         default:
10429         case Q3WAVEFUNC_NONE:
10430         case Q3WAVEFUNC_NOISE:
10431         case Q3WAVEFUNC_COUNT:
10432                 f = 0;
10433                 break;
10434         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10435         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10436         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10437         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10438         case Q3WAVEFUNC_TRIANGLE:
10439                 index *= 4;
10440                 f = index - floor(index);
10441                 if (index < 1)
10442                         f = f;
10443                 else if (index < 2)
10444                         f = 1 - f;
10445                 else if (index < 3)
10446                         f = -f;
10447                 else
10448                         f = -(1 - f);
10449                 break;
10450         }
10451         f = parms[0] + parms[1] * f;
10452         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10453                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10454         return (float) f;
10455 }
10456
10457 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10458 {
10459         int w, h, idx;
10460         float f;
10461         float tcmat[12];
10462         matrix4x4_t matrix, temp;
10463         switch(tcmod->tcmod)
10464         {
10465                 case Q3TCMOD_COUNT:
10466                 case Q3TCMOD_NONE:
10467                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10468                                 matrix = r_waterscrollmatrix;
10469                         else
10470                                 matrix = identitymatrix;
10471                         break;
10472                 case Q3TCMOD_ENTITYTRANSLATE:
10473                         // this is used in Q3 to allow the gamecode to control texcoord
10474                         // scrolling on the entity, which is not supported in darkplaces yet.
10475                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10476                         break;
10477                 case Q3TCMOD_ROTATE:
10478                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10479                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10480                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10481                         break;
10482                 case Q3TCMOD_SCALE:
10483                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10484                         break;
10485                 case Q3TCMOD_SCROLL:
10486                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10487                         break;
10488                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10489                         w = (int) tcmod->parms[0];
10490                         h = (int) tcmod->parms[1];
10491                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10492                         f = f - floor(f);
10493                         idx = (int) floor(f * w * h);
10494                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10495                         break;
10496                 case Q3TCMOD_STRETCH:
10497                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10498                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10499                         break;
10500                 case Q3TCMOD_TRANSFORM:
10501                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10502                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10503                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10504                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10505                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10506                         break;
10507                 case Q3TCMOD_TURBULENT:
10508                         // this is handled in the RSurf_PrepareVertices function
10509                         matrix = identitymatrix;
10510                         break;
10511         }
10512         temp = *texmatrix;
10513         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10514 }
10515
10516 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10517 {
10518         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10519         char name[MAX_QPATH];
10520         skinframe_t *skinframe;
10521         unsigned char pixels[296*194];
10522         strlcpy(cache->name, skinname, sizeof(cache->name));
10523         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10524         if (developer_loading.integer)
10525                 Con_Printf("loading %s\n", name);
10526         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10527         if (!skinframe || !skinframe->base)
10528         {
10529                 unsigned char *f;
10530                 fs_offset_t filesize;
10531                 skinframe = NULL;
10532                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10533                 if (f)
10534                 {
10535                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10536                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10537                         Mem_Free(f);
10538                 }
10539         }
10540         cache->skinframe = skinframe;
10541 }
10542
10543 texture_t *R_GetCurrentTexture(texture_t *t)
10544 {
10545         int i;
10546         const entity_render_t *ent = rsurface.entity;
10547         dp_model_t *model = ent->model;
10548         q3shaderinfo_layer_tcmod_t *tcmod;
10549
10550         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10551                 return t->currentframe;
10552         t->update_lastrenderframe = r_textureframe;
10553         t->update_lastrenderentity = (void *)ent;
10554
10555         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10556                 t->camera_entity = ent->entitynumber;
10557         else
10558                 t->camera_entity = 0;
10559
10560         // switch to an alternate material if this is a q1bsp animated material
10561         {
10562                 texture_t *texture = t;
10563                 int s = rsurface.ent_skinnum;
10564                 if ((unsigned int)s >= (unsigned int)model->numskins)
10565                         s = 0;
10566                 if (model->skinscenes)
10567                 {
10568                         if (model->skinscenes[s].framecount > 1)
10569                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10570                         else
10571                                 s = model->skinscenes[s].firstframe;
10572                 }
10573                 if (s > 0)
10574                         t = t + s * model->num_surfaces;
10575                 if (t->animated)
10576                 {
10577                         // use an alternate animation if the entity's frame is not 0,
10578                         // and only if the texture has an alternate animation
10579                         if (rsurface.ent_alttextures && t->anim_total[1])
10580                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10581                         else
10582                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10583                 }
10584                 texture->currentframe = t;
10585         }
10586
10587         // update currentskinframe to be a qw skin or animation frame
10588         if (rsurface.ent_qwskin >= 0)
10589         {
10590                 i = rsurface.ent_qwskin;
10591                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10592                 {
10593                         r_qwskincache_size = cl.maxclients;
10594                         if (r_qwskincache)
10595                                 Mem_Free(r_qwskincache);
10596                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10597                 }
10598                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10599                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10600                 t->currentskinframe = r_qwskincache[i].skinframe;
10601                 if (t->currentskinframe == NULL)
10602                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10603         }
10604         else if (t->numskinframes >= 2)
10605                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10606         if (t->backgroundnumskinframes >= 2)
10607                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10608
10609         t->currentmaterialflags = t->basematerialflags;
10610         t->currentalpha = rsurface.colormod[3];
10611         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10612                 t->currentalpha *= r_wateralpha.value;
10613         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10614                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10615         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10616                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10617         if (!(rsurface.ent_flags & RENDER_LIGHT))
10618                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10619         else if (FAKELIGHT_ENABLED)
10620         {
10621                         // no modellight if using fakelight for the map
10622         }
10623         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10624         {
10625                 // pick a model lighting mode
10626                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10627                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10628                 else
10629                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10630         }
10631         if (rsurface.ent_flags & RENDER_ADDITIVE)
10632                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10633         else if (t->currentalpha < 1)
10634                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10635         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10636                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10637         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10638                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10639         if (t->backgroundnumskinframes)
10640                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10641         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10642         {
10643                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10644                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10645         }
10646         else
10647                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10648         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10649                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10650
10651         // there is no tcmod
10652         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10653         {
10654                 t->currenttexmatrix = r_waterscrollmatrix;
10655                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10656         }
10657         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10658         {
10659                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10660                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10661         }
10662
10663         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10664                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10665         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10666                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10667
10668         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10669         if (t->currentskinframe->qpixels)
10670                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10671         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10672         if (!t->basetexture)
10673                 t->basetexture = r_texture_notexture;
10674         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10675         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10676         t->nmaptexture = t->currentskinframe->nmap;
10677         if (!t->nmaptexture)
10678                 t->nmaptexture = r_texture_blanknormalmap;
10679         t->glosstexture = r_texture_black;
10680         t->glowtexture = t->currentskinframe->glow;
10681         t->fogtexture = t->currentskinframe->fog;
10682         t->reflectmasktexture = t->currentskinframe->reflect;
10683         if (t->backgroundnumskinframes)
10684         {
10685                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10686                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10687                 t->backgroundglosstexture = r_texture_black;
10688                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10689                 if (!t->backgroundnmaptexture)
10690                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10691         }
10692         else
10693         {
10694                 t->backgroundbasetexture = r_texture_white;
10695                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10696                 t->backgroundglosstexture = r_texture_black;
10697                 t->backgroundglowtexture = NULL;
10698         }
10699         t->specularpower = r_shadow_glossexponent.value;
10700         // TODO: store reference values for these in the texture?
10701         t->specularscale = 0;
10702         if (r_shadow_gloss.integer > 0)
10703         {
10704                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10705                 {
10706                         if (r_shadow_glossintensity.value > 0)
10707                         {
10708                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10709                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10710                                 t->specularscale = r_shadow_glossintensity.value;
10711                         }
10712                 }
10713                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10714                 {
10715                         t->glosstexture = r_texture_white;
10716                         t->backgroundglosstexture = r_texture_white;
10717                         t->specularscale = r_shadow_gloss2intensity.value;
10718                         t->specularpower = r_shadow_gloss2exponent.value;
10719                 }
10720         }
10721         t->specularscale *= t->specularscalemod;
10722         t->specularpower *= t->specularpowermod;
10723
10724         // lightmaps mode looks bad with dlights using actual texturing, so turn
10725         // off the colormap and glossmap, but leave the normalmap on as it still
10726         // accurately represents the shading involved
10727         if (gl_lightmaps.integer)
10728         {
10729                 t->basetexture = r_texture_grey128;
10730                 t->pantstexture = r_texture_black;
10731                 t->shirttexture = r_texture_black;
10732                 t->nmaptexture = r_texture_blanknormalmap;
10733                 t->glosstexture = r_texture_black;
10734                 t->glowtexture = NULL;
10735                 t->fogtexture = NULL;
10736                 t->reflectmasktexture = NULL;
10737                 t->backgroundbasetexture = NULL;
10738                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10739                 t->backgroundglosstexture = r_texture_black;
10740                 t->backgroundglowtexture = NULL;
10741                 t->specularscale = 0;
10742                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10743         }
10744
10745         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10746         VectorClear(t->dlightcolor);
10747         t->currentnumlayers = 0;
10748         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10749         {
10750                 int blendfunc1, blendfunc2;
10751                 qboolean depthmask;
10752                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10753                 {
10754                         blendfunc1 = GL_SRC_ALPHA;
10755                         blendfunc2 = GL_ONE;
10756                 }
10757                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10758                 {
10759                         blendfunc1 = GL_SRC_ALPHA;
10760                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10761                 }
10762                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10763                 {
10764                         blendfunc1 = t->customblendfunc[0];
10765                         blendfunc2 = t->customblendfunc[1];
10766                 }
10767                 else
10768                 {
10769                         blendfunc1 = GL_ONE;
10770                         blendfunc2 = GL_ZERO;
10771                 }
10772                 // don't colormod evilblend textures
10773                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10774                         VectorSet(t->lightmapcolor, 1, 1, 1);
10775                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10776                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10777                 {
10778                         // fullbright is not affected by r_refdef.lightmapintensity
10779                         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]);
10780                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10781                                 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]);
10782                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10783                                 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]);
10784                 }
10785                 else
10786                 {
10787                         vec3_t ambientcolor;
10788                         float colorscale;
10789                         // set the color tint used for lights affecting this surface
10790                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10791                         colorscale = 2;
10792                         // q3bsp has no lightmap updates, so the lightstylevalue that
10793                         // would normally be baked into the lightmap must be
10794                         // applied to the color
10795                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10796                         if (model->type == mod_brushq3)
10797                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10798                         colorscale *= r_refdef.lightmapintensity;
10799                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10800                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10801                         // basic lit geometry
10802                         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]);
10803                         // add pants/shirt if needed
10804                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10805                                 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]);
10806                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10807                                 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]);
10808                         // now add ambient passes if needed
10809                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10810                         {
10811                                 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]);
10812                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10813                                         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]);
10814                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10815                                         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]);
10816                         }
10817                 }
10818                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10819                         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]);
10820                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10821                 {
10822                         // if this is opaque use alpha blend which will darken the earlier
10823                         // passes cheaply.
10824                         //
10825                         // if this is an alpha blended material, all the earlier passes
10826                         // were darkened by fog already, so we only need to add the fog
10827                         // color ontop through the fog mask texture
10828                         //
10829                         // if this is an additive blended material, all the earlier passes
10830                         // were darkened by fog already, and we should not add fog color
10831                         // (because the background was not darkened, there is no fog color
10832                         // that was lost behind it).
10833                         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]);
10834                 }
10835         }
10836
10837         return t->currentframe;
10838 }
10839
10840 rsurfacestate_t rsurface;
10841
10842 void R_Mesh_ResizeArrays(int newvertices)
10843 {
10844         unsigned char *base;
10845         size_t size;
10846         if (rsurface.array_size >= newvertices)
10847                 return;
10848         if (rsurface.array_base)
10849                 Mem_Free(rsurface.array_base);
10850         rsurface.array_size = (newvertices + 1023) & ~1023;
10851         size = 0;
10852         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10853         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10854         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10855         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10856         size += rsurface.array_size * sizeof(float[3]);
10857         size += rsurface.array_size * sizeof(float[3]);
10858         size += rsurface.array_size * sizeof(float[3]);
10859         size += rsurface.array_size * sizeof(float[3]);
10860         size += rsurface.array_size * sizeof(float[3]);
10861         size += rsurface.array_size * sizeof(float[3]);
10862         size += rsurface.array_size * sizeof(float[3]);
10863         size += rsurface.array_size * sizeof(float[3]);
10864         size += rsurface.array_size * sizeof(float[4]);
10865         size += rsurface.array_size * sizeof(float[2]);
10866         size += rsurface.array_size * sizeof(float[2]);
10867         size += rsurface.array_size * sizeof(float[4]);
10868         size += rsurface.array_size * sizeof(int[3]);
10869         size += rsurface.array_size * sizeof(unsigned short[3]);
10870         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10871         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10872         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10873         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10874         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10875         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10876         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10877         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10878         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10879         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10880         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10881         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10882         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10883         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10884         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10885         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10886         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10887         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10888         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10889 }
10890
10891 void RSurf_ActiveWorldEntity(void)
10892 {
10893         int newvertices;
10894         dp_model_t *model = r_refdef.scene.worldmodel;
10895         //if (rsurface.entity == r_refdef.scene.worldentity)
10896         //      return;
10897         rsurface.entity = r_refdef.scene.worldentity;
10898         rsurface.skeleton = NULL;
10899         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10900         rsurface.ent_skinnum = 0;
10901         rsurface.ent_qwskin = -1;
10902         rsurface.ent_shadertime = 0;
10903         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10904         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10905         if (rsurface.array_size < newvertices)
10906                 R_Mesh_ResizeArrays(newvertices);
10907         rsurface.matrix = identitymatrix;
10908         rsurface.inversematrix = identitymatrix;
10909         rsurface.matrixscale = 1;
10910         rsurface.inversematrixscale = 1;
10911         R_EntityMatrix(&identitymatrix);
10912         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10913         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10914         rsurface.fograngerecip = r_refdef.fograngerecip;
10915         rsurface.fogheightfade = r_refdef.fogheightfade;
10916         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10917         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10918         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10919         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10920         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10921         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10922         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10923         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10924         rsurface.colormod[3] = 1;
10925         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);
10926         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10927         rsurface.frameblend[0].lerp = 1;
10928         rsurface.ent_alttextures = false;
10929         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10930         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10931         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10932         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10933         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10934         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10935         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10936         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10937         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10938         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10939         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10940         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10941         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10942         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10943         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10944         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10945         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10946         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10947         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10948         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10949         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10950         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10951         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10952         rsurface.modelelement3i = model->surfmesh.data_element3i;
10953         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10954         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10955         rsurface.modelelement3s = model->surfmesh.data_element3s;
10956         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10957         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10958         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10959         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10960         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10961         rsurface.modelsurfaces = model->data_surfaces;
10962         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10963         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10964         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10965         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10966         rsurface.modelgeneratedvertex = false;
10967         rsurface.batchgeneratedvertex = false;
10968         rsurface.batchfirstvertex = 0;
10969         rsurface.batchnumvertices = 0;
10970         rsurface.batchfirsttriangle = 0;
10971         rsurface.batchnumtriangles = 0;
10972         rsurface.batchvertex3f  = NULL;
10973         rsurface.batchvertex3f_vertexbuffer = NULL;
10974         rsurface.batchvertex3f_bufferoffset = 0;
10975         rsurface.batchsvector3f = NULL;
10976         rsurface.batchsvector3f_vertexbuffer = NULL;
10977         rsurface.batchsvector3f_bufferoffset = 0;
10978         rsurface.batchtvector3f = NULL;
10979         rsurface.batchtvector3f_vertexbuffer = NULL;
10980         rsurface.batchtvector3f_bufferoffset = 0;
10981         rsurface.batchnormal3f  = NULL;
10982         rsurface.batchnormal3f_vertexbuffer = NULL;
10983         rsurface.batchnormal3f_bufferoffset = 0;
10984         rsurface.batchlightmapcolor4f = NULL;
10985         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10986         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10987         rsurface.batchtexcoordtexture2f = NULL;
10988         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10989         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10990         rsurface.batchtexcoordlightmap2f = NULL;
10991         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10992         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10993         rsurface.batchvertexmesh = NULL;
10994         rsurface.batchvertexmeshbuffer = NULL;
10995         rsurface.batchvertexposition = NULL;
10996         rsurface.batchvertexpositionbuffer = NULL;
10997         rsurface.batchelement3i = NULL;
10998         rsurface.batchelement3i_indexbuffer = NULL;
10999         rsurface.batchelement3i_bufferoffset = 0;
11000         rsurface.batchelement3s = NULL;
11001         rsurface.batchelement3s_indexbuffer = NULL;
11002         rsurface.batchelement3s_bufferoffset = 0;
11003         rsurface.passcolor4f = NULL;
11004         rsurface.passcolor4f_vertexbuffer = NULL;
11005         rsurface.passcolor4f_bufferoffset = 0;
11006 }
11007
11008 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11009 {
11010         int newvertices;
11011         dp_model_t *model = ent->model;
11012         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11013         //      return;
11014         rsurface.entity = (entity_render_t *)ent;
11015         rsurface.skeleton = ent->skeleton;
11016         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11017         rsurface.ent_skinnum = ent->skinnum;
11018         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;
11019         rsurface.ent_shadertime = ent->shadertime;
11020         rsurface.ent_flags = ent->flags;
11021         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
11022         if (rsurface.array_size < newvertices)
11023                 R_Mesh_ResizeArrays(newvertices);
11024         rsurface.matrix = ent->matrix;
11025         rsurface.inversematrix = ent->inversematrix;
11026         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11027         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11028         R_EntityMatrix(&rsurface.matrix);
11029         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11030         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11031         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11032         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11033         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11034         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11035         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11036         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11037         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11038         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11039         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11040         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11041         rsurface.colormod[3] = ent->alpha;
11042         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11043         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11044         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11045         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11046         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11047         if (ent->model->brush.submodel && !prepass)
11048         {
11049                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11050                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11051         }
11052         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11053         {
11054                 if (ent->animcache_vertex3f && !r_framedata_failed)
11055                 {
11056                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11057                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11058                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11059                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11060                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11061                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11062                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11063                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11064                 }
11065                 else if (wanttangents)
11066                 {
11067                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11068                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11069                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11070                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11071                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11072                         rsurface.modelvertexmesh = NULL;
11073                         rsurface.modelvertexmeshbuffer = NULL;
11074                         rsurface.modelvertexposition = NULL;
11075                         rsurface.modelvertexpositionbuffer = NULL;
11076                 }
11077                 else if (wantnormals)
11078                 {
11079                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11080                         rsurface.modelsvector3f = NULL;
11081                         rsurface.modeltvector3f = NULL;
11082                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11083                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11084                         rsurface.modelvertexmesh = NULL;
11085                         rsurface.modelvertexmeshbuffer = NULL;
11086                         rsurface.modelvertexposition = NULL;
11087                         rsurface.modelvertexpositionbuffer = NULL;
11088                 }
11089                 else
11090                 {
11091                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11092                         rsurface.modelsvector3f = NULL;
11093                         rsurface.modeltvector3f = NULL;
11094                         rsurface.modelnormal3f = NULL;
11095                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11096                         rsurface.modelvertexmesh = NULL;
11097                         rsurface.modelvertexmeshbuffer = NULL;
11098                         rsurface.modelvertexposition = NULL;
11099                         rsurface.modelvertexpositionbuffer = NULL;
11100                 }
11101                 rsurface.modelvertex3f_vertexbuffer = 0;
11102                 rsurface.modelvertex3f_bufferoffset = 0;
11103                 rsurface.modelsvector3f_vertexbuffer = 0;
11104                 rsurface.modelsvector3f_bufferoffset = 0;
11105                 rsurface.modeltvector3f_vertexbuffer = 0;
11106                 rsurface.modeltvector3f_bufferoffset = 0;
11107                 rsurface.modelnormal3f_vertexbuffer = 0;
11108                 rsurface.modelnormal3f_bufferoffset = 0;
11109                 rsurface.modelgeneratedvertex = true;
11110         }
11111         else
11112         {
11113                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11114                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11115                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11116                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11117                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11118                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11119                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11120                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11121                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11122                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11123                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11124                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11125                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11126                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11127                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11128                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11129                 rsurface.modelgeneratedvertex = false;
11130         }
11131         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11132         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11133         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11134         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11135         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11136         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11137         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11138         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11139         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11140         rsurface.modelelement3i = model->surfmesh.data_element3i;
11141         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11142         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11143         rsurface.modelelement3s = model->surfmesh.data_element3s;
11144         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11145         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11146         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11147         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11148         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11149         rsurface.modelsurfaces = model->data_surfaces;
11150         rsurface.batchgeneratedvertex = false;
11151         rsurface.batchfirstvertex = 0;
11152         rsurface.batchnumvertices = 0;
11153         rsurface.batchfirsttriangle = 0;
11154         rsurface.batchnumtriangles = 0;
11155         rsurface.batchvertex3f  = NULL;
11156         rsurface.batchvertex3f_vertexbuffer = NULL;
11157         rsurface.batchvertex3f_bufferoffset = 0;
11158         rsurface.batchsvector3f = NULL;
11159         rsurface.batchsvector3f_vertexbuffer = NULL;
11160         rsurface.batchsvector3f_bufferoffset = 0;
11161         rsurface.batchtvector3f = NULL;
11162         rsurface.batchtvector3f_vertexbuffer = NULL;
11163         rsurface.batchtvector3f_bufferoffset = 0;
11164         rsurface.batchnormal3f  = NULL;
11165         rsurface.batchnormal3f_vertexbuffer = NULL;
11166         rsurface.batchnormal3f_bufferoffset = 0;
11167         rsurface.batchlightmapcolor4f = NULL;
11168         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11169         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11170         rsurface.batchtexcoordtexture2f = NULL;
11171         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11172         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11173         rsurface.batchtexcoordlightmap2f = NULL;
11174         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11175         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11176         rsurface.batchvertexmesh = NULL;
11177         rsurface.batchvertexmeshbuffer = NULL;
11178         rsurface.batchvertexposition = NULL;
11179         rsurface.batchvertexpositionbuffer = NULL;
11180         rsurface.batchelement3i = NULL;
11181         rsurface.batchelement3i_indexbuffer = NULL;
11182         rsurface.batchelement3i_bufferoffset = 0;
11183         rsurface.batchelement3s = NULL;
11184         rsurface.batchelement3s_indexbuffer = NULL;
11185         rsurface.batchelement3s_bufferoffset = 0;
11186         rsurface.passcolor4f = NULL;
11187         rsurface.passcolor4f_vertexbuffer = NULL;
11188         rsurface.passcolor4f_bufferoffset = 0;
11189 }
11190
11191 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)
11192 {
11193         int newvertices;
11194
11195         rsurface.entity = r_refdef.scene.worldentity;
11196         rsurface.skeleton = NULL;
11197         rsurface.ent_skinnum = 0;
11198         rsurface.ent_qwskin = -1;
11199         rsurface.ent_shadertime = shadertime;
11200         rsurface.ent_flags = entflags;
11201         rsurface.modelnumvertices = numvertices;
11202         rsurface.modelnumtriangles = numtriangles;
11203         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11204         if (rsurface.array_size < newvertices)
11205                 R_Mesh_ResizeArrays(newvertices);
11206         rsurface.matrix = *matrix;
11207         rsurface.inversematrix = *inversematrix;
11208         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11209         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11210         R_EntityMatrix(&rsurface.matrix);
11211         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11212         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11213         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11214         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11215         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11216         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11217         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11218         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11219         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11220         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11221         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11222         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11223         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);
11224         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11225         rsurface.frameblend[0].lerp = 1;
11226         rsurface.ent_alttextures = false;
11227         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11228         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11229         if (wanttangents)
11230         {
11231                 rsurface.modelvertex3f = vertex3f;
11232                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11233                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11234                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11235         }
11236         else if (wantnormals)
11237         {
11238                 rsurface.modelvertex3f = vertex3f;
11239                 rsurface.modelsvector3f = NULL;
11240                 rsurface.modeltvector3f = NULL;
11241                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11242         }
11243         else
11244         {
11245                 rsurface.modelvertex3f = vertex3f;
11246                 rsurface.modelsvector3f = NULL;
11247                 rsurface.modeltvector3f = NULL;
11248                 rsurface.modelnormal3f = NULL;
11249         }
11250         rsurface.modelvertexmesh = NULL;
11251         rsurface.modelvertexmeshbuffer = NULL;
11252         rsurface.modelvertexposition = NULL;
11253         rsurface.modelvertexpositionbuffer = NULL;
11254         rsurface.modelvertex3f_vertexbuffer = 0;
11255         rsurface.modelvertex3f_bufferoffset = 0;
11256         rsurface.modelsvector3f_vertexbuffer = 0;
11257         rsurface.modelsvector3f_bufferoffset = 0;
11258         rsurface.modeltvector3f_vertexbuffer = 0;
11259         rsurface.modeltvector3f_bufferoffset = 0;
11260         rsurface.modelnormal3f_vertexbuffer = 0;
11261         rsurface.modelnormal3f_bufferoffset = 0;
11262         rsurface.modelgeneratedvertex = true;
11263         rsurface.modellightmapcolor4f  = color4f;
11264         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11265         rsurface.modellightmapcolor4f_bufferoffset = 0;
11266         rsurface.modeltexcoordtexture2f  = texcoord2f;
11267         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11268         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11269         rsurface.modeltexcoordlightmap2f  = NULL;
11270         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11271         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11272         rsurface.modelelement3i = element3i;
11273         rsurface.modelelement3i_indexbuffer = NULL;
11274         rsurface.modelelement3i_bufferoffset = 0;
11275         rsurface.modelelement3s = element3s;
11276         rsurface.modelelement3s_indexbuffer = NULL;
11277         rsurface.modelelement3s_bufferoffset = 0;
11278         rsurface.modellightmapoffsets = NULL;
11279         rsurface.modelsurfaces = NULL;
11280         rsurface.batchgeneratedvertex = false;
11281         rsurface.batchfirstvertex = 0;
11282         rsurface.batchnumvertices = 0;
11283         rsurface.batchfirsttriangle = 0;
11284         rsurface.batchnumtriangles = 0;
11285         rsurface.batchvertex3f  = NULL;
11286         rsurface.batchvertex3f_vertexbuffer = NULL;
11287         rsurface.batchvertex3f_bufferoffset = 0;
11288         rsurface.batchsvector3f = NULL;
11289         rsurface.batchsvector3f_vertexbuffer = NULL;
11290         rsurface.batchsvector3f_bufferoffset = 0;
11291         rsurface.batchtvector3f = NULL;
11292         rsurface.batchtvector3f_vertexbuffer = NULL;
11293         rsurface.batchtvector3f_bufferoffset = 0;
11294         rsurface.batchnormal3f  = NULL;
11295         rsurface.batchnormal3f_vertexbuffer = NULL;
11296         rsurface.batchnormal3f_bufferoffset = 0;
11297         rsurface.batchlightmapcolor4f = NULL;
11298         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11299         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11300         rsurface.batchtexcoordtexture2f = NULL;
11301         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11302         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11303         rsurface.batchtexcoordlightmap2f = NULL;
11304         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11305         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11306         rsurface.batchvertexmesh = NULL;
11307         rsurface.batchvertexmeshbuffer = NULL;
11308         rsurface.batchvertexposition = NULL;
11309         rsurface.batchvertexpositionbuffer = NULL;
11310         rsurface.batchelement3i = NULL;
11311         rsurface.batchelement3i_indexbuffer = NULL;
11312         rsurface.batchelement3i_bufferoffset = 0;
11313         rsurface.batchelement3s = NULL;
11314         rsurface.batchelement3s_indexbuffer = NULL;
11315         rsurface.batchelement3s_bufferoffset = 0;
11316         rsurface.passcolor4f = NULL;
11317         rsurface.passcolor4f_vertexbuffer = NULL;
11318         rsurface.passcolor4f_bufferoffset = 0;
11319
11320         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11321         {
11322                 if ((wantnormals || wanttangents) && !normal3f)
11323                 {
11324                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11325                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11326                 }
11327                 if (wanttangents && !svector3f)
11328                 {
11329                         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);
11330                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11331                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11332                 }
11333         }
11334 }
11335
11336 float RSurf_FogPoint(const float *v)
11337 {
11338         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11339         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11340         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11341         float FogHeightFade = r_refdef.fogheightfade;
11342         float fogfrac;
11343         unsigned int fogmasktableindex;
11344         if (r_refdef.fogplaneviewabove)
11345                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11346         else
11347                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11348         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11349         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11350 }
11351
11352 float RSurf_FogVertex(const float *v)
11353 {
11354         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11355         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11356         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11357         float FogHeightFade = rsurface.fogheightfade;
11358         float fogfrac;
11359         unsigned int fogmasktableindex;
11360         if (r_refdef.fogplaneviewabove)
11361                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11362         else
11363                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11364         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11365         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11366 }
11367
11368 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11369 {
11370         int i;
11371         for (i = 0;i < numelements;i++)
11372                 outelement3i[i] = inelement3i[i] + adjust;
11373 }
11374
11375 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11376 extern cvar_t gl_vbo;
11377 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11378 {
11379         int deformindex;
11380         int firsttriangle;
11381         int numtriangles;
11382         int firstvertex;
11383         int endvertex;
11384         int numvertices;
11385         int surfacefirsttriangle;
11386         int surfacenumtriangles;
11387         int surfacefirstvertex;
11388         int surfaceendvertex;
11389         int surfacenumvertices;
11390         int needsupdate;
11391         int i, j;
11392         qboolean gaps;
11393         qboolean dynamicvertex;
11394         float amplitude;
11395         float animpos;
11396         float scale;
11397         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11398         float waveparms[4];
11399         q3shaderinfo_deform_t *deform;
11400         const msurface_t *surface, *firstsurface;
11401         r_vertexposition_t *vertexposition;
11402         r_vertexmesh_t *vertexmesh;
11403         if (!texturenumsurfaces)
11404                 return;
11405         // find vertex range of this surface batch
11406         gaps = false;
11407         firstsurface = texturesurfacelist[0];
11408         firsttriangle = firstsurface->num_firsttriangle;
11409         numtriangles = 0;
11410         firstvertex = endvertex = firstsurface->num_firstvertex;
11411         for (i = 0;i < texturenumsurfaces;i++)
11412         {
11413                 surface = texturesurfacelist[i];
11414                 if (surface != firstsurface + i)
11415                         gaps = true;
11416                 surfacefirstvertex = surface->num_firstvertex;
11417                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11418                 surfacenumtriangles = surface->num_triangles;
11419                 if (firstvertex > surfacefirstvertex)
11420                         firstvertex = surfacefirstvertex;
11421                 if (endvertex < surfaceendvertex)
11422                         endvertex = surfaceendvertex;
11423                 numtriangles += surfacenumtriangles;
11424         }
11425
11426         // we now know the vertex range used, and if there are any gaps in it
11427         rsurface.batchfirstvertex = firstvertex;
11428         rsurface.batchnumvertices = endvertex - firstvertex;
11429         rsurface.batchfirsttriangle = firsttriangle;
11430         rsurface.batchnumtriangles = numtriangles;
11431
11432         // this variable holds flags for which properties have been updated that
11433         // may require regenerating vertexmesh or vertexposition arrays...
11434         needsupdate = 0;
11435
11436         // check if any dynamic vertex processing must occur
11437         dynamicvertex = false;
11438
11439         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11440                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11441         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11442         {
11443                 switch (deform->deform)
11444                 {
11445                 default:
11446                 case Q3DEFORM_PROJECTIONSHADOW:
11447                 case Q3DEFORM_TEXT0:
11448                 case Q3DEFORM_TEXT1:
11449                 case Q3DEFORM_TEXT2:
11450                 case Q3DEFORM_TEXT3:
11451                 case Q3DEFORM_TEXT4:
11452                 case Q3DEFORM_TEXT5:
11453                 case Q3DEFORM_TEXT6:
11454                 case Q3DEFORM_TEXT7:
11455                 case Q3DEFORM_NONE:
11456                         break;
11457                 case Q3DEFORM_AUTOSPRITE:
11458                         dynamicvertex = true;
11459                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11460                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11461                         break;
11462                 case Q3DEFORM_AUTOSPRITE2:
11463                         dynamicvertex = true;
11464                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11465                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11466                         break;
11467                 case Q3DEFORM_NORMAL:
11468                         dynamicvertex = true;
11469                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11470                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11471                         break;
11472                 case Q3DEFORM_WAVE:
11473                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11474                                 break; // if wavefunc is a nop, ignore this transform
11475                         dynamicvertex = true;
11476                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11477                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11478                         break;
11479                 case Q3DEFORM_BULGE:
11480                         dynamicvertex = true;
11481                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11482                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11483                         break;
11484                 case Q3DEFORM_MOVE:
11485                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11486                                 break; // if wavefunc is a nop, ignore this transform
11487                         dynamicvertex = true;
11488                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11489                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11490                         break;
11491                 }
11492         }
11493         switch(rsurface.texture->tcgen.tcgen)
11494         {
11495         default:
11496         case Q3TCGEN_TEXTURE:
11497                 break;
11498         case Q3TCGEN_LIGHTMAP:
11499                 dynamicvertex = true;
11500                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11501                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11502                 break;
11503         case Q3TCGEN_VECTOR:
11504                 dynamicvertex = true;
11505                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11506                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11507                 break;
11508         case Q3TCGEN_ENVIRONMENT:
11509                 dynamicvertex = true;
11510                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11511                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11512                 break;
11513         }
11514         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11515         {
11516                 dynamicvertex = true;
11517                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11518                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11519         }
11520
11521         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11522         {
11523                 dynamicvertex = true;
11524                 batchneed |= BATCHNEED_NOGAPS;
11525                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11526         }
11527
11528         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11529         {
11530                 dynamicvertex = true;
11531                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11532                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11533         }
11534
11535         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11536         {
11537                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11538                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11539                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11540                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11541                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11542                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11543                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11544         }
11545
11546         // when the model data has no vertex buffer (dynamic mesh), we need to
11547         // eliminate gaps
11548         if (!rsurface.modelvertexmeshbuffer)
11549                 batchneed |= BATCHNEED_NOGAPS;
11550
11551         // if needsupdate, we have to do a dynamic vertex batch for sure
11552         if (needsupdate & batchneed)
11553                 dynamicvertex = true;
11554
11555         // see if we need to build vertexmesh from arrays
11556         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11557                 dynamicvertex = true;
11558
11559         // see if we need to build vertexposition from arrays
11560         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11561                 dynamicvertex = true;
11562
11563         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11564         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11565                 dynamicvertex = true;
11566
11567         // if there is a chance of animated vertex colors, it's a dynamic batch
11568         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11569                 dynamicvertex = true;
11570
11571         rsurface.batchvertex3f = rsurface.modelvertex3f;
11572         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11573         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11574         rsurface.batchsvector3f = rsurface.modelsvector3f;
11575         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11576         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11577         rsurface.batchtvector3f = rsurface.modeltvector3f;
11578         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11579         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11580         rsurface.batchnormal3f = rsurface.modelnormal3f;
11581         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11582         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11583         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11584         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11585         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11586         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11587         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11588         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11589         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11590         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11591         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11592         rsurface.batchvertexposition = rsurface.modelvertexposition;
11593         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11594         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11595         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11596         rsurface.batchelement3i = rsurface.modelelement3i;
11597         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11598         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11599         rsurface.batchelement3s = rsurface.modelelement3s;
11600         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11601         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11602
11603         // if any dynamic vertex processing has to occur in software, we copy the
11604         // entire surface list together before processing to rebase the vertices
11605         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11606         //
11607         // if any gaps exist and we do not have a static vertex buffer, we have to
11608         // copy the surface list together to avoid wasting upload bandwidth on the
11609         // vertices in the gaps.
11610         //
11611         // if gaps exist and we have a static vertex buffer, we still have to
11612         // combine the index buffer ranges into one dynamic index buffer.
11613         //
11614         // in all cases we end up with data that can be drawn in one call.
11615
11616         if (!dynamicvertex)
11617         {
11618                 // static vertex data, just set pointers...
11619                 rsurface.batchgeneratedvertex = false;
11620                 // if there are gaps, we want to build a combined index buffer,
11621                 // otherwise use the original static buffer with an appropriate offset
11622                 if (gaps)
11623                 {
11624                         firsttriangle = 0;
11625                         numtriangles = 0;
11626                         for (i = 0;i < texturenumsurfaces;i++)
11627                         {
11628                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11629                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11630                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11631                                 numtriangles += surfacenumtriangles;
11632                         }
11633                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11634                         rsurface.batchelement3i_indexbuffer = NULL;
11635                         rsurface.batchelement3i_bufferoffset = 0;
11636                         rsurface.batchelement3s = NULL;
11637                         rsurface.batchelement3s_indexbuffer = NULL;
11638                         rsurface.batchelement3s_bufferoffset = 0;
11639                         if (endvertex <= 65536)
11640                         {
11641                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11642                                 for (i = 0;i < numtriangles*3;i++)
11643                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11644                         }
11645                         rsurface.batchfirsttriangle = firsttriangle;
11646                         rsurface.batchnumtriangles = numtriangles;
11647                 }
11648                 return;
11649         }
11650
11651         // something needs software processing, do it for real...
11652         // we only directly handle interleaved array data in this case...
11653         rsurface.batchgeneratedvertex = true;
11654
11655         // now copy the vertex data into a combined array and make an index array
11656         // (this is what Quake3 does all the time)
11657         //if (gaps || rsurface.batchfirstvertex)
11658         {
11659                 rsurface.batchvertexposition = NULL;
11660                 rsurface.batchvertexpositionbuffer = NULL;
11661                 rsurface.batchvertexmesh = NULL;
11662                 rsurface.batchvertexmeshbuffer = NULL;
11663                 rsurface.batchvertex3f = NULL;
11664                 rsurface.batchvertex3f_vertexbuffer = NULL;
11665                 rsurface.batchvertex3f_bufferoffset = 0;
11666                 rsurface.batchsvector3f = NULL;
11667                 rsurface.batchsvector3f_vertexbuffer = NULL;
11668                 rsurface.batchsvector3f_bufferoffset = 0;
11669                 rsurface.batchtvector3f = NULL;
11670                 rsurface.batchtvector3f_vertexbuffer = NULL;
11671                 rsurface.batchtvector3f_bufferoffset = 0;
11672                 rsurface.batchnormal3f = NULL;
11673                 rsurface.batchnormal3f_vertexbuffer = NULL;
11674                 rsurface.batchnormal3f_bufferoffset = 0;
11675                 rsurface.batchlightmapcolor4f = NULL;
11676                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11677                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11678                 rsurface.batchtexcoordtexture2f = NULL;
11679                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11680                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11681                 rsurface.batchtexcoordlightmap2f = NULL;
11682                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11683                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11684                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11685                 rsurface.batchelement3i_indexbuffer = NULL;
11686                 rsurface.batchelement3i_bufferoffset = 0;
11687                 rsurface.batchelement3s = NULL;
11688                 rsurface.batchelement3s_indexbuffer = NULL;
11689                 rsurface.batchelement3s_bufferoffset = 0;
11690                 // we'll only be setting up certain arrays as needed
11691                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11692                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11693                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11694                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11695                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11696                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11697                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11698                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11699                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11700                 {
11701                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11702                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11703                 }
11704                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11705                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11706                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11707                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11708                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11709                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11710                 numvertices = 0;
11711                 numtriangles = 0;
11712                 for (i = 0;i < texturenumsurfaces;i++)
11713                 {
11714                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11715                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11716                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11717                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11718                         // copy only the data requested
11719                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11720                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11721                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11722                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11723                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11724                         {
11725                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11726                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11727                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11728                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11729                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11730                                 {
11731                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11732                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11733                                 }
11734                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11735                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11736                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11737                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11738                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11739                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11740                         }
11741                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11742                         numvertices += surfacenumvertices;
11743                         numtriangles += surfacenumtriangles;
11744                 }
11745
11746                 // generate a 16bit index array as well if possible
11747                 // (in general, dynamic batches fit)
11748                 if (numvertices <= 65536)
11749                 {
11750                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11751                         for (i = 0;i < numtriangles*3;i++)
11752                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11753                 }
11754
11755                 // since we've copied everything, the batch now starts at 0
11756                 rsurface.batchfirstvertex = 0;
11757                 rsurface.batchnumvertices = numvertices;
11758                 rsurface.batchfirsttriangle = 0;
11759                 rsurface.batchnumtriangles = numtriangles;
11760         }
11761
11762         // q1bsp surfaces rendered in vertex color mode have to have colors
11763         // calculated based on lightstyles
11764         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11765         {
11766                 // generate color arrays for the surfaces in this list
11767                 int c[4];
11768                 int scale;
11769                 int size3;
11770                 const int *offsets;
11771                 const unsigned char *lm;
11772                 numvertices = 0;
11773                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11774                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11775                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11776                 for (i = 0;i < texturenumsurfaces;i++)
11777                 {
11778                         surface = texturesurfacelist[i];
11779                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11780                         surfacenumvertices = surface->num_vertices;
11781                         if (surface->lightmapinfo->samples)
11782                         {
11783                                 for (j = 0;j < surfacenumvertices;j++)
11784                                 {
11785                                         lm = surface->lightmapinfo->samples + offsets[j];
11786                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11787                                         VectorScale(lm, scale, c);
11788                                         if (surface->lightmapinfo->styles[1] != 255)
11789                                         {
11790                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11791                                                 lm += size3;
11792                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11793                                                 VectorMA(c, scale, lm, c);
11794                                                 if (surface->lightmapinfo->styles[2] != 255)
11795                                                 {
11796                                                         lm += size3;
11797                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11798                                                         VectorMA(c, scale, lm, c);
11799                                                         if (surface->lightmapinfo->styles[3] != 255)
11800                                                         {
11801                                                                 lm += size3;
11802                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11803                                                                 VectorMA(c, scale, lm, c);
11804                                                         }
11805                                                 }
11806                                         }
11807                                         c[0] >>= 15;
11808                                         c[1] >>= 15;
11809                                         c[2] >>= 15;
11810                                         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);
11811                                         numvertices++;
11812                                 }
11813                         }
11814                         else
11815                         {
11816                                 for (j = 0;j < surfacenumvertices;j++)
11817                                 {
11818                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11819                                         numvertices++;
11820                                 }
11821                         }
11822                 }
11823         }
11824
11825         // if vertices are deformed (sprite flares and things in maps, possibly
11826         // water waves, bulges and other deformations), modify the copied vertices
11827         // in place
11828         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11829         {
11830                 switch (deform->deform)
11831                 {
11832                 default:
11833                 case Q3DEFORM_PROJECTIONSHADOW:
11834                 case Q3DEFORM_TEXT0:
11835                 case Q3DEFORM_TEXT1:
11836                 case Q3DEFORM_TEXT2:
11837                 case Q3DEFORM_TEXT3:
11838                 case Q3DEFORM_TEXT4:
11839                 case Q3DEFORM_TEXT5:
11840                 case Q3DEFORM_TEXT6:
11841                 case Q3DEFORM_TEXT7:
11842                 case Q3DEFORM_NONE:
11843                         break;
11844                 case Q3DEFORM_AUTOSPRITE:
11845                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11846                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11847                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11848                         VectorNormalize(newforward);
11849                         VectorNormalize(newright);
11850                         VectorNormalize(newup);
11851                         // a single autosprite surface can contain multiple sprites...
11852                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11853                         {
11854                                 VectorClear(center);
11855                                 for (i = 0;i < 4;i++)
11856                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11857                                 VectorScale(center, 0.25f, center);
11858                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11859                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11860                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11861                                 for (i = 0;i < 4;i++)
11862                                 {
11863                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11864                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11865                                 }
11866                         }
11867                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11868                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11869                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11870                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11871                         rsurface.batchvertex3f_vertexbuffer = NULL;
11872                         rsurface.batchvertex3f_bufferoffset = 0;
11873                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11874                         rsurface.batchsvector3f_vertexbuffer = NULL;
11875                         rsurface.batchsvector3f_bufferoffset = 0;
11876                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11877                         rsurface.batchtvector3f_vertexbuffer = NULL;
11878                         rsurface.batchtvector3f_bufferoffset = 0;
11879                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11880                         rsurface.batchnormal3f_vertexbuffer = NULL;
11881                         rsurface.batchnormal3f_bufferoffset = 0;
11882                         break;
11883                 case Q3DEFORM_AUTOSPRITE2:
11884                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11885                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11886                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11887                         VectorNormalize(newforward);
11888                         VectorNormalize(newright);
11889                         VectorNormalize(newup);
11890                         {
11891                                 const float *v1, *v2;
11892                                 vec3_t start, end;
11893                                 float f, l;
11894                                 struct
11895                                 {
11896                                         float length2;
11897                                         const float *v1;
11898                                         const float *v2;
11899                                 }
11900                                 shortest[2];
11901                                 memset(shortest, 0, sizeof(shortest));
11902                                 // a single autosprite surface can contain multiple sprites...
11903                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11904                                 {
11905                                         VectorClear(center);
11906                                         for (i = 0;i < 4;i++)
11907                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11908                                         VectorScale(center, 0.25f, center);
11909                                         // find the two shortest edges, then use them to define the
11910                                         // axis vectors for rotating around the central axis
11911                                         for (i = 0;i < 6;i++)
11912                                         {
11913                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11914                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11915                                                 l = VectorDistance2(v1, v2);
11916                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11917                                                 if (v1[2] != v2[2])
11918                                                         l += (1.0f / 1024.0f);
11919                                                 if (shortest[0].length2 > l || i == 0)
11920                                                 {
11921                                                         shortest[1] = shortest[0];
11922                                                         shortest[0].length2 = l;
11923                                                         shortest[0].v1 = v1;
11924                                                         shortest[0].v2 = v2;
11925                                                 }
11926                                                 else if (shortest[1].length2 > l || i == 1)
11927                                                 {
11928                                                         shortest[1].length2 = l;
11929                                                         shortest[1].v1 = v1;
11930                                                         shortest[1].v2 = v2;
11931                                                 }
11932                                         }
11933                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11934                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11935                                         // this calculates the right vector from the shortest edge
11936                                         // and the up vector from the edge midpoints
11937                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11938                                         VectorNormalize(right);
11939                                         VectorSubtract(end, start, up);
11940                                         VectorNormalize(up);
11941                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11942                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11943                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11944                                         VectorNegate(forward, forward);
11945                                         VectorReflect(forward, 0, up, forward);
11946                                         VectorNormalize(forward);
11947                                         CrossProduct(up, forward, newright);
11948                                         VectorNormalize(newright);
11949                                         // rotate the quad around the up axis vector, this is made
11950                                         // especially easy by the fact we know the quad is flat,
11951                                         // so we only have to subtract the center position and
11952                                         // measure distance along the right vector, and then
11953                                         // multiply that by the newright vector and add back the
11954                                         // center position
11955                                         // we also need to subtract the old position to undo the
11956                                         // displacement from the center, which we do with a
11957                                         // DotProduct, the subtraction/addition of center is also
11958                                         // optimized into DotProducts here
11959                                         l = DotProduct(right, center);
11960                                         for (i = 0;i < 4;i++)
11961                                         {
11962                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11963                                                 f = DotProduct(right, v1) - l;
11964                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11965                                         }
11966                                 }
11967                         }
11968                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11969                         rsurface.batchvertex3f_vertexbuffer = NULL;
11970                         rsurface.batchvertex3f_bufferoffset = 0;
11971                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11972                         {
11973                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11974                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11975                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11976                                 rsurface.batchnormal3f_bufferoffset = 0;
11977                         }
11978                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11979                         {
11980                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11981                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11982                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11983                                 rsurface.batchsvector3f_bufferoffset = 0;
11984                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11985                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11986                                 rsurface.batchtvector3f_bufferoffset = 0;
11987                         }
11988                         break;
11989                 case Q3DEFORM_NORMAL:
11990                         // deform the normals to make reflections wavey
11991                         for (j = 0;j < rsurface.batchnumvertices;j++)
11992                         {
11993                                 float vertex[3];
11994                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11995                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11996                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11997                                 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]);
11998                                 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]);
11999                                 VectorNormalize(normal);
12000                         }
12001                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12002                         rsurface.batchnormal3f_vertexbuffer = NULL;
12003                         rsurface.batchnormal3f_bufferoffset = 0;
12004                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12005                         {
12006                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12007                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12008                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12009                                 rsurface.batchsvector3f_bufferoffset = 0;
12010                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12011                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12012                                 rsurface.batchtvector3f_bufferoffset = 0;
12013                         }
12014                         break;
12015                 case Q3DEFORM_WAVE:
12016                         // deform vertex array to make wavey water and flags and such
12017                         waveparms[0] = deform->waveparms[0];
12018                         waveparms[1] = deform->waveparms[1];
12019                         waveparms[2] = deform->waveparms[2];
12020                         waveparms[3] = deform->waveparms[3];
12021                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12022                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12023                         // this is how a divisor of vertex influence on deformation
12024                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12025                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12026                         for (j = 0;j < rsurface.batchnumvertices;j++)
12027                         {
12028                                 // if the wavefunc depends on time, evaluate it per-vertex
12029                                 if (waveparms[3])
12030                                 {
12031                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12032                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12033                                 }
12034                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12035                         }
12036                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12037                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12038                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12039                         rsurface.batchvertex3f_vertexbuffer = NULL;
12040                         rsurface.batchvertex3f_bufferoffset = 0;
12041                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12042                         rsurface.batchnormal3f_vertexbuffer = NULL;
12043                         rsurface.batchnormal3f_bufferoffset = 0;
12044                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12045                         {
12046                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12047                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12048                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12049                                 rsurface.batchsvector3f_bufferoffset = 0;
12050                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12051                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12052                                 rsurface.batchtvector3f_bufferoffset = 0;
12053                         }
12054                         break;
12055                 case Q3DEFORM_BULGE:
12056                         // deform vertex array to make the surface have moving bulges
12057                         for (j = 0;j < rsurface.batchnumvertices;j++)
12058                         {
12059                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12060                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12061                         }
12062                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12063                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12064                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12065                         rsurface.batchvertex3f_vertexbuffer = NULL;
12066                         rsurface.batchvertex3f_bufferoffset = 0;
12067                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12068                         rsurface.batchnormal3f_vertexbuffer = NULL;
12069                         rsurface.batchnormal3f_bufferoffset = 0;
12070                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12071                         {
12072                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12073                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12074                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12075                                 rsurface.batchsvector3f_bufferoffset = 0;
12076                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12077                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12078                                 rsurface.batchtvector3f_bufferoffset = 0;
12079                         }
12080                         break;
12081                 case Q3DEFORM_MOVE:
12082                         // deform vertex array
12083                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12084                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12085                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12086                         VectorScale(deform->parms, scale, waveparms);
12087                         for (j = 0;j < rsurface.batchnumvertices;j++)
12088                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12089                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12090                         rsurface.batchvertex3f_vertexbuffer = NULL;
12091                         rsurface.batchvertex3f_bufferoffset = 0;
12092                         break;
12093                 }
12094         }
12095
12096         // generate texcoords based on the chosen texcoord source
12097         switch(rsurface.texture->tcgen.tcgen)
12098         {
12099         default:
12100         case Q3TCGEN_TEXTURE:
12101                 break;
12102         case Q3TCGEN_LIGHTMAP:
12103                 if (rsurface.batchtexcoordlightmap2f)
12104                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12105                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12106                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12107                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12108                 break;
12109         case Q3TCGEN_VECTOR:
12110                 for (j = 0;j < rsurface.batchnumvertices;j++)
12111                 {
12112                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12113                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12114                 }
12115                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12116                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12117                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12118                 break;
12119         case Q3TCGEN_ENVIRONMENT:
12120                 // make environment reflections using a spheremap
12121                 for (j = 0;j < rsurface.batchnumvertices;j++)
12122                 {
12123                         // identical to Q3A's method, but executed in worldspace so
12124                         // carried models can be shiny too
12125
12126                         float viewer[3], d, reflected[3], worldreflected[3];
12127
12128                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12129                         // VectorNormalize(viewer);
12130
12131                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12132
12133                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12134                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12135                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12136                         // note: this is proportinal to viewer, so we can normalize later
12137
12138                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12139                         VectorNormalize(worldreflected);
12140
12141                         // note: this sphere map only uses world x and z!
12142                         // so positive and negative y will LOOK THE SAME.
12143                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12144                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12145                 }
12146                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12147                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12148                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12149                 break;
12150         }
12151         // the only tcmod that needs software vertex processing is turbulent, so
12152         // check for it here and apply the changes if needed
12153         // and we only support that as the first one
12154         // (handling a mixture of turbulent and other tcmods would be problematic
12155         //  without punting it entirely to a software path)
12156         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12157         {
12158                 amplitude = rsurface.texture->tcmods[0].parms[1];
12159                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12160                 for (j = 0;j < rsurface.batchnumvertices;j++)
12161                 {
12162                         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);
12163                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12164                 }
12165                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12166                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12167                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12168         }
12169
12170         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12171         {
12172                 // convert the modified arrays to vertex structs
12173                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12174                 rsurface.batchvertexmeshbuffer = NULL;
12175                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12176                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12177                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12178                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12179                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12180                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12181                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12182                 {
12183                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12184                         {
12185                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12186                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12187                         }
12188                 }
12189                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12190                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12191                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12192                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12193                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12194                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12195                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12196                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12197                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12198         }
12199
12200         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12201         {
12202                 // convert the modified arrays to vertex structs
12203                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12204                 rsurface.batchvertexpositionbuffer = NULL;
12205                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12206                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12207                 else
12208                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12209                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12210         }
12211 }
12212
12213 void RSurf_DrawBatch(void)
12214 {
12215         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12216         // through the pipeline, killing it earlier in the pipeline would have
12217         // per-surface overhead rather than per-batch overhead, so it's best to
12218         // reject it here, before it hits glDraw.
12219         if (rsurface.batchnumtriangles == 0)
12220                 return;
12221 #if 0
12222         // batch debugging code
12223         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12224         {
12225                 int i;
12226                 int j;
12227                 int c;
12228                 const int *e;
12229                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12230                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12231                 {
12232                         c = e[i];
12233                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12234                         {
12235                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12236                                 {
12237                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12238                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
12239                                         break;
12240                                 }
12241                         }
12242                 }
12243         }
12244 #endif
12245         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);
12246 }
12247
12248 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12249 {
12250         // pick the closest matching water plane
12251         int planeindex, vertexindex, bestplaneindex = -1;
12252         float d, bestd;
12253         vec3_t vert;
12254         const float *v;
12255         r_waterstate_waterplane_t *p;
12256         qboolean prepared = false;
12257         bestd = 0;
12258         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12259         {
12260                 if(p->camera_entity != rsurface.texture->camera_entity)
12261                         continue;
12262                 d = 0;
12263                 if(!prepared)
12264                 {
12265                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12266                         prepared = true;
12267                         if(rsurface.batchnumvertices == 0)
12268                                 break;
12269                 }
12270                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12271                 {
12272                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12273                         d += fabs(PlaneDiff(vert, &p->plane));
12274                 }
12275                 if (bestd > d || bestplaneindex < 0)
12276                 {
12277                         bestd = d;
12278                         bestplaneindex = planeindex;
12279                 }
12280         }
12281         return bestplaneindex;
12282         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12283         // this situation though, as it might be better to render single larger
12284         // batches with useless stuff (backface culled for example) than to
12285         // render multiple smaller batches
12286 }
12287
12288 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12289 {
12290         int i;
12291         for (i = 0;i < rsurface.batchnumvertices;i++)
12292                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12293         rsurface.passcolor4f = rsurface.array_passcolor4f;
12294         rsurface.passcolor4f_vertexbuffer = 0;
12295         rsurface.passcolor4f_bufferoffset = 0;
12296 }
12297
12298 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12299 {
12300         int i;
12301         float f;
12302         const float *v;
12303         const float *c;
12304         float *c2;
12305         if (rsurface.passcolor4f)
12306         {
12307                 // generate color arrays
12308                 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)
12309                 {
12310                         f = RSurf_FogVertex(v);
12311                         c2[0] = c[0] * f;
12312                         c2[1] = c[1] * f;
12313                         c2[2] = c[2] * f;
12314                         c2[3] = c[3];
12315                 }
12316         }
12317         else
12318         {
12319                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12320                 {
12321                         f = RSurf_FogVertex(v);
12322                         c2[0] = f;
12323                         c2[1] = f;
12324                         c2[2] = f;
12325                         c2[3] = 1;
12326                 }
12327         }
12328         rsurface.passcolor4f = rsurface.array_passcolor4f;
12329         rsurface.passcolor4f_vertexbuffer = 0;
12330         rsurface.passcolor4f_bufferoffset = 0;
12331 }
12332
12333 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12334 {
12335         int i;
12336         float f;
12337         const float *v;
12338         const float *c;
12339         float *c2;
12340         if (!rsurface.passcolor4f)
12341                 return;
12342         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)
12343         {
12344                 f = RSurf_FogVertex(v);
12345                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12346                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12347                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12348                 c2[3] = c[3];
12349         }
12350         rsurface.passcolor4f = rsurface.array_passcolor4f;
12351         rsurface.passcolor4f_vertexbuffer = 0;
12352         rsurface.passcolor4f_bufferoffset = 0;
12353 }
12354
12355 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12356 {
12357         int i;
12358         const float *c;
12359         float *c2;
12360         if (!rsurface.passcolor4f)
12361                 return;
12362         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12363         {
12364                 c2[0] = c[0] * r;
12365                 c2[1] = c[1] * g;
12366                 c2[2] = c[2] * b;
12367                 c2[3] = c[3] * a;
12368         }
12369         rsurface.passcolor4f = rsurface.array_passcolor4f;
12370         rsurface.passcolor4f_vertexbuffer = 0;
12371         rsurface.passcolor4f_bufferoffset = 0;
12372 }
12373
12374 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12375 {
12376         int i;
12377         const float *c;
12378         float *c2;
12379         if (!rsurface.passcolor4f)
12380                 return;
12381         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12382         {
12383                 c2[0] = c[0] + r_refdef.scene.ambient;
12384                 c2[1] = c[1] + r_refdef.scene.ambient;
12385                 c2[2] = c[2] + r_refdef.scene.ambient;
12386                 c2[3] = c[3];
12387         }
12388         rsurface.passcolor4f = rsurface.array_passcolor4f;
12389         rsurface.passcolor4f_vertexbuffer = 0;
12390         rsurface.passcolor4f_bufferoffset = 0;
12391 }
12392
12393 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12394 {
12395         // TODO: optimize
12396         rsurface.passcolor4f = NULL;
12397         rsurface.passcolor4f_vertexbuffer = 0;
12398         rsurface.passcolor4f_bufferoffset = 0;
12399         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12400         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12401         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12402         GL_Color(r, g, b, a);
12403         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12404         RSurf_DrawBatch();
12405 }
12406
12407 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12408 {
12409         // TODO: optimize applyfog && applycolor case
12410         // just apply fog if necessary, and tint the fog color array if necessary
12411         rsurface.passcolor4f = NULL;
12412         rsurface.passcolor4f_vertexbuffer = 0;
12413         rsurface.passcolor4f_bufferoffset = 0;
12414         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12415         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12416         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12417         GL_Color(r, g, b, a);
12418         RSurf_DrawBatch();
12419 }
12420
12421 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12422 {
12423         // TODO: optimize
12424         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12425         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12426         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12427         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12428         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12429         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12430         GL_Color(r, g, b, a);
12431         RSurf_DrawBatch();
12432 }
12433
12434 static void RSurf_DrawBatch_GL11_ClampColor(void)
12435 {
12436         int i;
12437         const float *c1;
12438         float *c2;
12439         if (!rsurface.passcolor4f)
12440                 return;
12441         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12442         {
12443                 c2[0] = bound(0.0f, c1[0], 1.0f);
12444                 c2[1] = bound(0.0f, c1[1], 1.0f);
12445                 c2[2] = bound(0.0f, c1[2], 1.0f);
12446                 c2[3] = bound(0.0f, c1[3], 1.0f);
12447         }
12448 }
12449
12450 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12451 {
12452         int i;
12453         float f;
12454         const float *v;
12455         const float *n;
12456         float *c;
12457         //vec3_t eyedir;
12458
12459         // fake shading
12460         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)
12461         {
12462                 f = -DotProduct(r_refdef.view.forward, n);
12463                 f = max(0, f);
12464                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12465                 f *= r_refdef.lightmapintensity;
12466                 Vector4Set(c, f, f, f, 1);
12467         }
12468
12469         rsurface.passcolor4f = rsurface.array_passcolor4f;
12470         rsurface.passcolor4f_vertexbuffer = 0;
12471         rsurface.passcolor4f_bufferoffset = 0;
12472 }
12473
12474 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12475 {
12476         RSurf_DrawBatch_GL11_ApplyFakeLight();
12477         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12478         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12479         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12480         GL_Color(r, g, b, a);
12481         RSurf_DrawBatch();
12482 }
12483
12484 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12485 {
12486         int i;
12487         float f;
12488         float alpha;
12489         const float *v;
12490         const float *n;
12491         float *c;
12492         vec3_t ambientcolor;
12493         vec3_t diffusecolor;
12494         vec3_t lightdir;
12495         // TODO: optimize
12496         // model lighting
12497         VectorCopy(rsurface.modellight_lightdir, lightdir);
12498         f = 0.5f * r_refdef.lightmapintensity;
12499         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12500         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12501         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12502         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12503         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12504         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12505         alpha = *a;
12506         if (VectorLength2(diffusecolor) > 0)
12507         {
12508                 // q3-style directional shading
12509                 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)
12510                 {
12511                         if ((f = DotProduct(n, lightdir)) > 0)
12512                                 VectorMA(ambientcolor, f, diffusecolor, c);
12513                         else
12514                                 VectorCopy(ambientcolor, c);
12515                         c[3] = alpha;
12516                 }
12517                 *r = 1;
12518                 *g = 1;
12519                 *b = 1;
12520                 *a = 1;
12521                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12522                 rsurface.passcolor4f_vertexbuffer = 0;
12523                 rsurface.passcolor4f_bufferoffset = 0;
12524                 *applycolor = false;
12525         }
12526         else
12527         {
12528                 *r = ambientcolor[0];
12529                 *g = ambientcolor[1];
12530                 *b = ambientcolor[2];
12531                 rsurface.passcolor4f = NULL;
12532                 rsurface.passcolor4f_vertexbuffer = 0;
12533                 rsurface.passcolor4f_bufferoffset = 0;
12534         }
12535 }
12536
12537 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12538 {
12539         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12540         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12541         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12542         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12543         GL_Color(r, g, b, a);
12544         RSurf_DrawBatch();
12545 }
12546
12547 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12548 {
12549         int i;
12550         float f;
12551         const float *v;
12552         float *c;
12553         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12554         {
12555                 f = 1 - RSurf_FogVertex(v);
12556                 c[0] = r;
12557                 c[1] = g;
12558                 c[2] = b;
12559                 c[3] = f * a;
12560         }
12561 }
12562
12563 void RSurf_SetupDepthAndCulling(void)
12564 {
12565         // submodels are biased to avoid z-fighting with world surfaces that they
12566         // may be exactly overlapping (avoids z-fighting artifacts on certain
12567         // doors and things in Quake maps)
12568         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12569         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12570         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12571         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12572 }
12573
12574 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12575 {
12576         // transparent sky would be ridiculous
12577         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12578                 return;
12579         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12580         skyrenderlater = true;
12581         RSurf_SetupDepthAndCulling();
12582         GL_DepthMask(true);
12583         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12584         // skymasking on them, and Quake3 never did sky masking (unlike
12585         // software Quake and software Quake2), so disable the sky masking
12586         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12587         // and skymasking also looks very bad when noclipping outside the
12588         // level, so don't use it then either.
12589         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12590         {
12591                 R_Mesh_ResetTextureState();
12592                 if (skyrendermasked)
12593                 {
12594                         R_SetupShader_DepthOrShadow();
12595                         // depth-only (masking)
12596                         GL_ColorMask(0,0,0,0);
12597                         // just to make sure that braindead drivers don't draw
12598                         // anything despite that colormask...
12599                         GL_BlendFunc(GL_ZERO, GL_ONE);
12600                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12601                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12602                 }
12603                 else
12604                 {
12605                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12606                         // fog sky
12607                         GL_BlendFunc(GL_ONE, GL_ZERO);
12608                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12609                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12610                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12611                 }
12612                 RSurf_DrawBatch();
12613                 if (skyrendermasked)
12614                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12615         }
12616         R_Mesh_ResetTextureState();
12617         GL_Color(1, 1, 1, 1);
12618 }
12619
12620 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12621 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12622 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12623 {
12624         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12625                 return;
12626         if (prepass)
12627         {
12628                 // render screenspace normalmap to texture
12629                 GL_DepthMask(true);
12630                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12631                 RSurf_DrawBatch();
12632                 return;
12633         }
12634
12635         // bind lightmap texture
12636
12637         // water/refraction/reflection/camera surfaces have to be handled specially
12638         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12639         {
12640                 int start, end, startplaneindex;
12641                 for (start = 0;start < texturenumsurfaces;start = end)
12642                 {
12643                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12644                         if(startplaneindex < 0)
12645                         {
12646                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12647                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12648                                 end = start + 1;
12649                                 continue;
12650                         }
12651                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12652                                 ;
12653                         // now that we have a batch using the same planeindex, render it
12654                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12655                         {
12656                                 // render water or distortion background
12657                                 GL_DepthMask(true);
12658                                 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));
12659                                 RSurf_DrawBatch();
12660                                 // blend surface on top
12661                                 GL_DepthMask(false);
12662                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12663                                 RSurf_DrawBatch();
12664                         }
12665                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12666                         {
12667                                 // render surface with reflection texture as input
12668                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12669                                 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));
12670                                 RSurf_DrawBatch();
12671                         }
12672                 }
12673                 return;
12674         }
12675
12676         // render surface batch normally
12677         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12678         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12679         RSurf_DrawBatch();
12680 }
12681
12682 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12683 {
12684         // OpenGL 1.3 path - anything not completely ancient
12685         qboolean applycolor;
12686         qboolean applyfog;
12687         int layerindex;
12688         const texturelayer_t *layer;
12689         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);
12690         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12691
12692         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12693         {
12694                 vec4_t layercolor;
12695                 int layertexrgbscale;
12696                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12697                 {
12698                         if (layerindex == 0)
12699                                 GL_AlphaTest(true);
12700                         else
12701                         {
12702                                 GL_AlphaTest(false);
12703                                 GL_DepthFunc(GL_EQUAL);
12704                         }
12705                 }
12706                 GL_DepthMask(layer->depthmask && writedepth);
12707                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12708                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12709                 {
12710                         layertexrgbscale = 4;
12711                         VectorScale(layer->color, 0.25f, layercolor);
12712                 }
12713                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12714                 {
12715                         layertexrgbscale = 2;
12716                         VectorScale(layer->color, 0.5f, layercolor);
12717                 }
12718                 else
12719                 {
12720                         layertexrgbscale = 1;
12721                         VectorScale(layer->color, 1.0f, layercolor);
12722                 }
12723                 layercolor[3] = layer->color[3];
12724                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12725                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12726                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12727                 switch (layer->type)
12728                 {
12729                 case TEXTURELAYERTYPE_LITTEXTURE:
12730                         // single-pass lightmapped texture with 2x rgbscale
12731                         R_Mesh_TexBind(0, r_texture_white);
12732                         R_Mesh_TexMatrix(0, NULL);
12733                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12734                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12735                         R_Mesh_TexBind(1, layer->texture);
12736                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12737                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12738                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12739                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12740                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12741                         else if (FAKELIGHT_ENABLED)
12742                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12743                         else if (rsurface.uselightmaptexture)
12744                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12745                         else
12746                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12747                         break;
12748                 case TEXTURELAYERTYPE_TEXTURE:
12749                         // singletexture unlit texture with transparency support
12750                         R_Mesh_TexBind(0, layer->texture);
12751                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12752                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12753                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12754                         R_Mesh_TexBind(1, 0);
12755                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12756                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12757                         break;
12758                 case TEXTURELAYERTYPE_FOG:
12759                         // singletexture fogging
12760                         if (layer->texture)
12761                         {
12762                                 R_Mesh_TexBind(0, layer->texture);
12763                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12764                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12765                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12766                         }
12767                         else
12768                         {
12769                                 R_Mesh_TexBind(0, 0);
12770                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12771                         }
12772                         R_Mesh_TexBind(1, 0);
12773                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12774                         // generate a color array for the fog pass
12775                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12776                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12777                         RSurf_DrawBatch();
12778                         break;
12779                 default:
12780                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12781                 }
12782         }
12783         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12784         {
12785                 GL_DepthFunc(GL_LEQUAL);
12786                 GL_AlphaTest(false);
12787         }
12788 }
12789
12790 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12791 {
12792         // OpenGL 1.1 - crusty old voodoo path
12793         qboolean applyfog;
12794         int layerindex;
12795         const texturelayer_t *layer;
12796         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);
12797         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12798
12799         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12800         {
12801                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12802                 {
12803                         if (layerindex == 0)
12804                                 GL_AlphaTest(true);
12805                         else
12806                         {
12807                                 GL_AlphaTest(false);
12808                                 GL_DepthFunc(GL_EQUAL);
12809                         }
12810                 }
12811                 GL_DepthMask(layer->depthmask && writedepth);
12812                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12813                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12814                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12815                 switch (layer->type)
12816                 {
12817                 case TEXTURELAYERTYPE_LITTEXTURE:
12818                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12819                         {
12820                                 // two-pass lit texture with 2x rgbscale
12821                                 // first the lightmap pass
12822                                 R_Mesh_TexBind(0, r_texture_white);
12823                                 R_Mesh_TexMatrix(0, NULL);
12824                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12825                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12826                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12827                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12828                                 else if (FAKELIGHT_ENABLED)
12829                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12830                                 else if (rsurface.uselightmaptexture)
12831                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12832                                 else
12833                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12834                                 // then apply the texture to it
12835                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12836                                 R_Mesh_TexBind(0, layer->texture);
12837                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12838                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12839                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12840                                 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);
12841                         }
12842                         else
12843                         {
12844                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12845                                 R_Mesh_TexBind(0, layer->texture);
12846                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12847                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12848                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12849                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12850                                         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);
12851                                 else
12852                                         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);
12853                         }
12854                         break;
12855                 case TEXTURELAYERTYPE_TEXTURE:
12856                         // singletexture unlit texture with transparency support
12857                         R_Mesh_TexBind(0, layer->texture);
12858                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12859                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12860                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12861                         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);
12862                         break;
12863                 case TEXTURELAYERTYPE_FOG:
12864                         // singletexture fogging
12865                         if (layer->texture)
12866                         {
12867                                 R_Mesh_TexBind(0, layer->texture);
12868                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12869                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12870                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12871                         }
12872                         else
12873                         {
12874                                 R_Mesh_TexBind(0, 0);
12875                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12876                         }
12877                         // generate a color array for the fog pass
12878                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12879                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12880                         RSurf_DrawBatch();
12881                         break;
12882                 default:
12883                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12884                 }
12885         }
12886         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12887         {
12888                 GL_DepthFunc(GL_LEQUAL);
12889                 GL_AlphaTest(false);
12890         }
12891 }
12892
12893 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12894 {
12895         int vi;
12896         int j;
12897         r_vertexgeneric_t *batchvertex;
12898         float c[4];
12899
12900         GL_AlphaTest(false);
12901 //      R_Mesh_ResetTextureState();
12902         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12903
12904         if(rsurface.texture && rsurface.texture->currentskinframe)
12905         {
12906                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12907                 c[3] *= rsurface.texture->currentalpha;
12908         }
12909         else
12910         {
12911                 c[0] = 1;
12912                 c[1] = 0;
12913                 c[2] = 1;
12914                 c[3] = 1;
12915         }
12916
12917         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12918         {
12919                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12920                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12921                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12922         }
12923
12924         // brighten it up (as texture value 127 means "unlit")
12925         c[0] *= 2 * r_refdef.view.colorscale;
12926         c[1] *= 2 * r_refdef.view.colorscale;
12927         c[2] *= 2 * r_refdef.view.colorscale;
12928
12929         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12930                 c[3] *= r_wateralpha.value;
12931
12932         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12933         {
12934                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12935                 GL_DepthMask(false);
12936         }
12937         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12938         {
12939                 GL_BlendFunc(GL_ONE, GL_ONE);
12940                 GL_DepthMask(false);
12941         }
12942         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12943         {
12944                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12945                 GL_DepthMask(false);
12946         }
12947         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12948         {
12949                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12950                 GL_DepthMask(false);
12951         }
12952         else
12953         {
12954                 GL_BlendFunc(GL_ONE, GL_ZERO);
12955                 GL_DepthMask(writedepth);
12956         }
12957
12958         if (r_showsurfaces.integer == 3)
12959         {
12960                 rsurface.passcolor4f = NULL;
12961
12962                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12963                 {
12964                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12965
12966                         rsurface.passcolor4f = NULL;
12967                         rsurface.passcolor4f_vertexbuffer = 0;
12968                         rsurface.passcolor4f_bufferoffset = 0;
12969                 }
12970                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12971                 {
12972                         qboolean applycolor = true;
12973                         float one = 1.0;
12974
12975                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12976
12977                         r_refdef.lightmapintensity = 1;
12978                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12979                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12980                 }
12981                 else if (FAKELIGHT_ENABLED)
12982                 {
12983                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12984
12985                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12986                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12987                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12988                 }
12989                 else
12990                 {
12991                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12992
12993                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12994                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12995                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12996                 }
12997
12998                 if(!rsurface.passcolor4f)
12999                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13000
13001                 RSurf_DrawBatch_GL11_ApplyAmbient();
13002                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13003                 if(r_refdef.fogenabled)
13004                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13005                 RSurf_DrawBatch_GL11_ClampColor();
13006
13007                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13008                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13009                 RSurf_DrawBatch();
13010         }
13011         else if (!r_refdef.view.showdebug)
13012         {
13013                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13014                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13015                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13016                 {
13017                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13018                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13019                 }
13020                 R_Mesh_PrepareVertices_Generic_Unlock();
13021                 RSurf_DrawBatch();
13022         }
13023         else if (r_showsurfaces.integer == 4)
13024         {
13025                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13026                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13027                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13028                 {
13029                         unsigned char c = vi << 3;
13030                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13031                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13032                 }
13033                 R_Mesh_PrepareVertices_Generic_Unlock();
13034                 RSurf_DrawBatch();
13035         }
13036         else if (r_showsurfaces.integer == 2)
13037         {
13038                 const int *e;
13039                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13040                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13041                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13042                 {
13043                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13044                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13045                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13046                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13047                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13048                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13049                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13050                 }
13051                 R_Mesh_PrepareVertices_Generic_Unlock();
13052                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13053         }
13054         else
13055         {
13056                 int texturesurfaceindex;
13057                 int k;
13058                 const msurface_t *surface;
13059                 unsigned char surfacecolor4ub[4];
13060                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13061                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13062                 vi = 0;
13063                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13064                 {
13065                         surface = texturesurfacelist[texturesurfaceindex];
13066                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13067                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13068                         for (j = 0;j < surface->num_vertices;j++)
13069                         {
13070                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13071                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13072                                 vi++;
13073                         }
13074                 }
13075                 R_Mesh_PrepareVertices_Generic_Unlock();
13076                 RSurf_DrawBatch();
13077         }
13078 }
13079
13080 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13081 {
13082         CHECKGLERROR
13083         RSurf_SetupDepthAndCulling();
13084         if (r_showsurfaces.integer)
13085         {
13086                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13087                 return;
13088         }
13089         switch (vid.renderpath)
13090         {
13091         case RENDERPATH_GL20:
13092         case RENDERPATH_CGGL:
13093         case RENDERPATH_D3D9:
13094         case RENDERPATH_D3D10:
13095         case RENDERPATH_D3D11:
13096                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13097                 break;
13098         case RENDERPATH_GL13:
13099                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13100                 break;
13101         case RENDERPATH_GL11:
13102                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13103                 break;
13104         }
13105         CHECKGLERROR
13106 }
13107
13108 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13109 {
13110         CHECKGLERROR
13111         RSurf_SetupDepthAndCulling();
13112         if (r_showsurfaces.integer)
13113         {
13114                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13115                 return;
13116         }
13117         switch (vid.renderpath)
13118         {
13119         case RENDERPATH_GL20:
13120         case RENDERPATH_CGGL:
13121         case RENDERPATH_D3D9:
13122         case RENDERPATH_D3D10:
13123         case RENDERPATH_D3D11:
13124                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13125                 break;
13126         case RENDERPATH_GL13:
13127                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13128                 break;
13129         case RENDERPATH_GL11:
13130                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13131                 break;
13132         }
13133         CHECKGLERROR
13134 }
13135
13136 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13137 {
13138         int i, j;
13139         int texturenumsurfaces, endsurface;
13140         texture_t *texture;
13141         const msurface_t *surface;
13142 #define MAXBATCH_TRANSPARENTSURFACES 256
13143         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13144
13145         // if the model is static it doesn't matter what value we give for
13146         // wantnormals and wanttangents, so this logic uses only rules applicable
13147         // to a model, knowing that they are meaningless otherwise
13148         if (ent == r_refdef.scene.worldentity)
13149                 RSurf_ActiveWorldEntity();
13150         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13151                 RSurf_ActiveModelEntity(ent, false, false, false);
13152         else
13153         {
13154                 switch (vid.renderpath)
13155                 {
13156                 case RENDERPATH_GL20:
13157                 case RENDERPATH_CGGL:
13158                 case RENDERPATH_D3D9:
13159                 case RENDERPATH_D3D10:
13160                 case RENDERPATH_D3D11:
13161                         RSurf_ActiveModelEntity(ent, true, true, false);
13162                         break;
13163                 case RENDERPATH_GL13:
13164                 case RENDERPATH_GL11:
13165                         RSurf_ActiveModelEntity(ent, true, false, false);
13166                         break;
13167                 }
13168         }
13169
13170         if (r_transparentdepthmasking.integer)
13171         {
13172                 qboolean setup = false;
13173                 for (i = 0;i < numsurfaces;i = j)
13174                 {
13175                         j = i + 1;
13176                         surface = rsurface.modelsurfaces + surfacelist[i];
13177                         texture = surface->texture;
13178                         rsurface.texture = R_GetCurrentTexture(texture);
13179                         rsurface.lightmaptexture = NULL;
13180                         rsurface.deluxemaptexture = NULL;
13181                         rsurface.uselightmaptexture = false;
13182                         // scan ahead until we find a different texture
13183                         endsurface = min(i + 1024, numsurfaces);
13184                         texturenumsurfaces = 0;
13185                         texturesurfacelist[texturenumsurfaces++] = surface;
13186                         for (;j < endsurface;j++)
13187                         {
13188                                 surface = rsurface.modelsurfaces + surfacelist[j];
13189                                 if (texture != surface->texture)
13190                                         break;
13191                                 texturesurfacelist[texturenumsurfaces++] = surface;
13192                         }
13193                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13194                                 continue;
13195                         // render the range of surfaces as depth
13196                         if (!setup)
13197                         {
13198                                 setup = true;
13199                                 GL_ColorMask(0,0,0,0);
13200                                 GL_Color(1,1,1,1);
13201                                 GL_DepthTest(true);
13202                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13203                                 GL_DepthMask(true);
13204                                 GL_AlphaTest(false);
13205 //                              R_Mesh_ResetTextureState();
13206                                 R_SetupShader_DepthOrShadow();
13207                         }
13208                         RSurf_SetupDepthAndCulling();
13209                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13210                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13211                         RSurf_DrawBatch();
13212                 }
13213                 if (setup)
13214                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13215         }
13216
13217         for (i = 0;i < numsurfaces;i = j)
13218         {
13219                 j = i + 1;
13220                 surface = rsurface.modelsurfaces + surfacelist[i];
13221                 texture = surface->texture;
13222                 rsurface.texture = R_GetCurrentTexture(texture);
13223                 // scan ahead until we find a different texture
13224                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13225                 texturenumsurfaces = 0;
13226                 texturesurfacelist[texturenumsurfaces++] = surface;
13227                 if(FAKELIGHT_ENABLED)
13228                 {
13229                         rsurface.lightmaptexture = NULL;
13230                         rsurface.deluxemaptexture = NULL;
13231                         rsurface.uselightmaptexture = false;
13232                         for (;j < endsurface;j++)
13233                         {
13234                                 surface = rsurface.modelsurfaces + surfacelist[j];
13235                                 if (texture != surface->texture)
13236                                         break;
13237                                 texturesurfacelist[texturenumsurfaces++] = surface;
13238                         }
13239                 }
13240                 else
13241                 {
13242                         rsurface.lightmaptexture = surface->lightmaptexture;
13243                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13244                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13245                         for (;j < endsurface;j++)
13246                         {
13247                                 surface = rsurface.modelsurfaces + surfacelist[j];
13248                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13249                                         break;
13250                                 texturesurfacelist[texturenumsurfaces++] = surface;
13251                         }
13252                 }
13253                 // render the range of surfaces
13254                 if (ent == r_refdef.scene.worldentity)
13255                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13256                 else
13257                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13258         }
13259         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13260         GL_AlphaTest(false);
13261 }
13262
13263 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13264 {
13265         // transparent surfaces get pushed off into the transparent queue
13266         int surfacelistindex;
13267         const msurface_t *surface;
13268         vec3_t tempcenter, center;
13269         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13270         {
13271                 surface = texturesurfacelist[surfacelistindex];
13272                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13273                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13274                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13275                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13276                 if (queueentity->transparent_offset) // transparent offset
13277                 {
13278                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13279                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13280                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13281                 }
13282                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13283         }
13284 }
13285
13286 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13287 {
13288         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13289                 return;
13290         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13291                 return;
13292         RSurf_SetupDepthAndCulling();
13293         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13294         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13295         RSurf_DrawBatch();
13296 }
13297
13298 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13299 {
13300         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13301         CHECKGLERROR
13302         if (depthonly)
13303                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13304         else if (prepass)
13305         {
13306                 if (!rsurface.texture->currentnumlayers)
13307                         return;
13308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13309                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13310                 else
13311                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13312         }
13313         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13314                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13315         else if (!rsurface.texture->currentnumlayers)
13316                 return;
13317         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13318         {
13319                 // in the deferred case, transparent surfaces were queued during prepass
13320                 if (!r_shadow_usingdeferredprepass)
13321                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13322         }
13323         else
13324         {
13325                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13326                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13327         }
13328         CHECKGLERROR
13329 }
13330
13331 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13332 {
13333         int i, j;
13334         texture_t *texture;
13335         // break the surface list down into batches by texture and use of lightmapping
13336         for (i = 0;i < numsurfaces;i = j)
13337         {
13338                 j = i + 1;
13339                 // texture is the base texture pointer, rsurface.texture is the
13340                 // current frame/skin the texture is directing us to use (for example
13341                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13342                 // use skin 1 instead)
13343                 texture = surfacelist[i]->texture;
13344                 rsurface.texture = R_GetCurrentTexture(texture);
13345                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13346                 {
13347                         // if this texture is not the kind we want, skip ahead to the next one
13348                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13349                                 ;
13350                         continue;
13351                 }
13352                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13353                 {
13354                         rsurface.lightmaptexture = NULL;
13355                         rsurface.deluxemaptexture = NULL;
13356                         rsurface.uselightmaptexture = false;
13357                         // simply scan ahead until we find a different texture or lightmap state
13358                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13359                                 ;
13360                 }
13361                 else
13362                 {
13363                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13364                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13365                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13366                         // simply scan ahead until we find a different texture or lightmap state
13367                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13368                                 ;
13369                 }
13370                 // render the range of surfaces
13371                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13372         }
13373 }
13374
13375 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13376 {
13377         CHECKGLERROR
13378         if (depthonly)
13379                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13380         else if (prepass)
13381         {
13382                 if (!rsurface.texture->currentnumlayers)
13383                         return;
13384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13385                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13386                 else
13387                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13388         }
13389         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13390                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13391         else if (!rsurface.texture->currentnumlayers)
13392                 return;
13393         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13394         {
13395                 // in the deferred case, transparent surfaces were queued during prepass
13396                 if (!r_shadow_usingdeferredprepass)
13397                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13398         }
13399         else
13400         {
13401                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13402                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13403         }
13404         CHECKGLERROR
13405 }
13406
13407 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13408 {
13409         int i, j;
13410         texture_t *texture;
13411         // break the surface list down into batches by texture and use of lightmapping
13412         for (i = 0;i < numsurfaces;i = j)
13413         {
13414                 j = i + 1;
13415                 // texture is the base texture pointer, rsurface.texture is the
13416                 // current frame/skin the texture is directing us to use (for example
13417                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13418                 // use skin 1 instead)
13419                 texture = surfacelist[i]->texture;
13420                 rsurface.texture = R_GetCurrentTexture(texture);
13421                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13422                 {
13423                         // if this texture is not the kind we want, skip ahead to the next one
13424                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13425                                 ;
13426                         continue;
13427                 }
13428                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13429                 {
13430                         rsurface.lightmaptexture = NULL;
13431                         rsurface.deluxemaptexture = NULL;
13432                         rsurface.uselightmaptexture = false;
13433                         // simply scan ahead until we find a different texture or lightmap state
13434                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13435                                 ;
13436                 }
13437                 else
13438                 {
13439                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13440                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13441                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13442                         // simply scan ahead until we find a different texture or lightmap state
13443                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13444                                 ;
13445                 }
13446                 // render the range of surfaces
13447                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13448         }
13449 }
13450
13451 float locboxvertex3f[6*4*3] =
13452 {
13453         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13454         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13455         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13456         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13457         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13458         1,0,0, 0,0,0, 0,1,0, 1,1,0
13459 };
13460
13461 unsigned short locboxelements[6*2*3] =
13462 {
13463          0, 1, 2, 0, 2, 3,
13464          4, 5, 6, 4, 6, 7,
13465          8, 9,10, 8,10,11,
13466         12,13,14, 12,14,15,
13467         16,17,18, 16,18,19,
13468         20,21,22, 20,22,23
13469 };
13470
13471 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13472 {
13473         int i, j;
13474         cl_locnode_t *loc = (cl_locnode_t *)ent;
13475         vec3_t mins, size;
13476         float vertex3f[6*4*3];
13477         CHECKGLERROR
13478         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13479         GL_DepthMask(false);
13480         GL_DepthRange(0, 1);
13481         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13482         GL_DepthTest(true);
13483         GL_CullFace(GL_NONE);
13484         R_EntityMatrix(&identitymatrix);
13485
13486 //      R_Mesh_ResetTextureState();
13487
13488         i = surfacelist[0];
13489         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13490                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13491                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13492                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13493
13494         if (VectorCompare(loc->mins, loc->maxs))
13495         {
13496                 VectorSet(size, 2, 2, 2);
13497                 VectorMA(loc->mins, -0.5f, size, mins);
13498         }
13499         else
13500         {
13501                 VectorCopy(loc->mins, mins);
13502                 VectorSubtract(loc->maxs, loc->mins, size);
13503         }
13504
13505         for (i = 0;i < 6*4*3;)
13506                 for (j = 0;j < 3;j++, i++)
13507                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13508
13509         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13510         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13511         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13512 }
13513
13514 void R_DrawLocs(void)
13515 {
13516         int index;
13517         cl_locnode_t *loc, *nearestloc;
13518         vec3_t center;
13519         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13520         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13521         {
13522                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13523                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13524         }
13525 }
13526
13527 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13528 {
13529         if (decalsystem->decals)
13530                 Mem_Free(decalsystem->decals);
13531         memset(decalsystem, 0, sizeof(*decalsystem));
13532 }
13533
13534 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)
13535 {
13536         tridecal_t *decal;
13537         tridecal_t *decals;
13538         int i;
13539
13540         // expand or initialize the system
13541         if (decalsystem->maxdecals <= decalsystem->numdecals)
13542         {
13543                 decalsystem_t old = *decalsystem;
13544                 qboolean useshortelements;
13545                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13546                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13547                 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)));
13548                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13549                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13550                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13551                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13552                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13553                 if (decalsystem->numdecals)
13554                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13555                 if (old.decals)
13556                         Mem_Free(old.decals);
13557                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13558                         decalsystem->element3i[i] = i;
13559                 if (useshortelements)
13560                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13561                                 decalsystem->element3s[i] = i;
13562         }
13563
13564         // grab a decal and search for another free slot for the next one
13565         decals = decalsystem->decals;
13566         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13567         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13568                 ;
13569         decalsystem->freedecal = i;
13570         if (decalsystem->numdecals <= i)
13571                 decalsystem->numdecals = i + 1;
13572
13573         // initialize the decal
13574         decal->lived = 0;
13575         decal->triangleindex = triangleindex;
13576         decal->surfaceindex = surfaceindex;
13577         decal->decalsequence = decalsequence;
13578         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13579         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13580         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13581         decal->color4ub[0][3] = 255;
13582         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13583         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13584         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13585         decal->color4ub[1][3] = 255;
13586         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13587         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13588         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13589         decal->color4ub[2][3] = 255;
13590         decal->vertex3f[0][0] = v0[0];
13591         decal->vertex3f[0][1] = v0[1];
13592         decal->vertex3f[0][2] = v0[2];
13593         decal->vertex3f[1][0] = v1[0];
13594         decal->vertex3f[1][1] = v1[1];
13595         decal->vertex3f[1][2] = v1[2];
13596         decal->vertex3f[2][0] = v2[0];
13597         decal->vertex3f[2][1] = v2[1];
13598         decal->vertex3f[2][2] = v2[2];
13599         decal->texcoord2f[0][0] = t0[0];
13600         decal->texcoord2f[0][1] = t0[1];
13601         decal->texcoord2f[1][0] = t1[0];
13602         decal->texcoord2f[1][1] = t1[1];
13603         decal->texcoord2f[2][0] = t2[0];
13604         decal->texcoord2f[2][1] = t2[1];
13605 }
13606
13607 extern cvar_t cl_decals_bias;
13608 extern cvar_t cl_decals_models;
13609 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13610 // baseparms, parms, temps
13611 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)
13612 {
13613         int cornerindex;
13614         int index;
13615         float v[9][3];
13616         const float *vertex3f;
13617         int numpoints;
13618         float points[2][9][3];
13619         float temp[3];
13620         float tc[9][2];
13621         float f;
13622         float c[9][4];
13623         const int *e;
13624
13625         e = rsurface.modelelement3i + 3*triangleindex;
13626
13627         vertex3f = rsurface.modelvertex3f;
13628
13629         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13630         {
13631                 index = 3*e[cornerindex];
13632                 VectorCopy(vertex3f + index, v[cornerindex]);
13633         }
13634         // cull backfaces
13635         //TriangleNormal(v[0], v[1], v[2], normal);
13636         //if (DotProduct(normal, localnormal) < 0.0f)
13637         //      continue;
13638         // clip by each of the box planes formed from the projection matrix
13639         // if anything survives, we emit the decal
13640         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]);
13641         if (numpoints < 3)
13642                 return;
13643         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]);
13644         if (numpoints < 3)
13645                 return;
13646         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]);
13647         if (numpoints < 3)
13648                 return;
13649         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]);
13650         if (numpoints < 3)
13651                 return;
13652         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]);
13653         if (numpoints < 3)
13654                 return;
13655         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]);
13656         if (numpoints < 3)
13657                 return;
13658         // some part of the triangle survived, so we have to accept it...
13659         if (dynamic)
13660         {
13661                 // dynamic always uses the original triangle
13662                 numpoints = 3;
13663                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13664                 {
13665                         index = 3*e[cornerindex];
13666                         VectorCopy(vertex3f + index, v[cornerindex]);
13667                 }
13668         }
13669         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13670         {
13671                 // convert vertex positions to texcoords
13672                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13673                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13674                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13675                 // calculate distance fade from the projection origin
13676                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13677                 f = bound(0.0f, f, 1.0f);
13678                 c[cornerindex][0] = r * f;
13679                 c[cornerindex][1] = g * f;
13680                 c[cornerindex][2] = b * f;
13681                 c[cornerindex][3] = 1.0f;
13682                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13683         }
13684         if (dynamic)
13685                 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);
13686         else
13687                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13688                         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);
13689 }
13690 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)
13691 {
13692         matrix4x4_t projection;
13693         decalsystem_t *decalsystem;
13694         qboolean dynamic;
13695         dp_model_t *model;
13696         const msurface_t *surface;
13697         const msurface_t *surfaces;
13698         const int *surfacelist;
13699         const texture_t *texture;
13700         int numtriangles;
13701         int numsurfacelist;
13702         int surfacelistindex;
13703         int surfaceindex;
13704         int triangleindex;
13705         float localorigin[3];
13706         float localnormal[3];
13707         float localmins[3];
13708         float localmaxs[3];
13709         float localsize;
13710         //float normal[3];
13711         float planes[6][4];
13712         float angles[3];
13713         bih_t *bih;
13714         int bih_triangles_count;
13715         int bih_triangles[256];
13716         int bih_surfaces[256];
13717
13718         decalsystem = &ent->decalsystem;
13719         model = ent->model;
13720         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13721         {
13722                 R_DecalSystem_Reset(&ent->decalsystem);
13723                 return;
13724         }
13725
13726         if (!model->brush.data_leafs && !cl_decals_models.integer)
13727         {
13728                 if (decalsystem->model)
13729                         R_DecalSystem_Reset(decalsystem);
13730                 return;
13731         }
13732
13733         if (decalsystem->model != model)
13734                 R_DecalSystem_Reset(decalsystem);
13735         decalsystem->model = model;
13736
13737         RSurf_ActiveModelEntity(ent, false, false, false);
13738
13739         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13740         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13741         VectorNormalize(localnormal);
13742         localsize = worldsize*rsurface.inversematrixscale;
13743         localmins[0] = localorigin[0] - localsize;
13744         localmins[1] = localorigin[1] - localsize;
13745         localmins[2] = localorigin[2] - localsize;
13746         localmaxs[0] = localorigin[0] + localsize;
13747         localmaxs[1] = localorigin[1] + localsize;
13748         localmaxs[2] = localorigin[2] + localsize;
13749
13750         //VectorCopy(localnormal, planes[4]);
13751         //VectorVectors(planes[4], planes[2], planes[0]);
13752         AnglesFromVectors(angles, localnormal, NULL, false);
13753         AngleVectors(angles, planes[0], planes[2], planes[4]);
13754         VectorNegate(planes[0], planes[1]);
13755         VectorNegate(planes[2], planes[3]);
13756         VectorNegate(planes[4], planes[5]);
13757         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13758         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13759         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13760         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13761         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13762         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13763
13764 #if 1
13765 // works
13766 {
13767         matrix4x4_t forwardprojection;
13768         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13769         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13770 }
13771 #else
13772 // broken
13773 {
13774         float projectionvector[4][3];
13775         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13776         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13777         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13778         projectionvector[0][0] = planes[0][0] * ilocalsize;
13779         projectionvector[0][1] = planes[1][0] * ilocalsize;
13780         projectionvector[0][2] = planes[2][0] * ilocalsize;
13781         projectionvector[1][0] = planes[0][1] * ilocalsize;
13782         projectionvector[1][1] = planes[1][1] * ilocalsize;
13783         projectionvector[1][2] = planes[2][1] * ilocalsize;
13784         projectionvector[2][0] = planes[0][2] * ilocalsize;
13785         projectionvector[2][1] = planes[1][2] * ilocalsize;
13786         projectionvector[2][2] = planes[2][2] * ilocalsize;
13787         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13788         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13789         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13790         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13791 }
13792 #endif
13793
13794         dynamic = model->surfmesh.isanimated;
13795         numsurfacelist = model->nummodelsurfaces;
13796         surfacelist = model->sortedmodelsurfaces;
13797         surfaces = model->data_surfaces;
13798
13799         bih = NULL;
13800         bih_triangles_count = -1;
13801         if(!dynamic)
13802         {
13803                 if(model->render_bih.numleafs)
13804                         bih = &model->render_bih;
13805                 else if(model->collision_bih.numleafs)
13806                         bih = &model->collision_bih;
13807         }
13808         if(bih)
13809                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13810         if(bih_triangles_count == 0)
13811                 return;
13812         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13813                 return;
13814         if(bih_triangles_count > 0)
13815         {
13816                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13817                 {
13818                         surfaceindex = bih_surfaces[triangleindex];
13819                         surface = surfaces + surfaceindex;
13820                         texture = surface->texture;
13821                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13822                                 continue;
13823                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13824                                 continue;
13825                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13826                 }
13827         }
13828         else
13829         {
13830                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13831                 {
13832                         surfaceindex = surfacelist[surfacelistindex];
13833                         surface = surfaces + surfaceindex;
13834                         // check cull box first because it rejects more than any other check
13835                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13836                                 continue;
13837                         // skip transparent surfaces
13838                         texture = surface->texture;
13839                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13840                                 continue;
13841                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13842                                 continue;
13843                         numtriangles = surface->num_triangles;
13844                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13845                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13846                 }
13847         }
13848 }
13849
13850 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13851 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)
13852 {
13853         int renderentityindex;
13854         float worldmins[3];
13855         float worldmaxs[3];
13856         entity_render_t *ent;
13857
13858         if (!cl_decals_newsystem.integer)
13859                 return;
13860
13861         worldmins[0] = worldorigin[0] - worldsize;
13862         worldmins[1] = worldorigin[1] - worldsize;
13863         worldmins[2] = worldorigin[2] - worldsize;
13864         worldmaxs[0] = worldorigin[0] + worldsize;
13865         worldmaxs[1] = worldorigin[1] + worldsize;
13866         worldmaxs[2] = worldorigin[2] + worldsize;
13867
13868         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13869
13870         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13871         {
13872                 ent = r_refdef.scene.entities[renderentityindex];
13873                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13874                         continue;
13875
13876                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13877         }
13878 }
13879
13880 typedef struct r_decalsystem_splatqueue_s
13881 {
13882         vec3_t worldorigin;
13883         vec3_t worldnormal;
13884         float color[4];
13885         float tcrange[4];
13886         float worldsize;
13887         int decalsequence;
13888 }
13889 r_decalsystem_splatqueue_t;
13890
13891 int r_decalsystem_numqueued = 0;
13892 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13893
13894 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)
13895 {
13896         r_decalsystem_splatqueue_t *queue;
13897
13898         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13899                 return;
13900
13901         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13902         VectorCopy(worldorigin, queue->worldorigin);
13903         VectorCopy(worldnormal, queue->worldnormal);
13904         Vector4Set(queue->color, r, g, b, a);
13905         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13906         queue->worldsize = worldsize;
13907         queue->decalsequence = cl.decalsequence++;
13908 }
13909
13910 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13911 {
13912         int i;
13913         r_decalsystem_splatqueue_t *queue;
13914
13915         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13916                 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);
13917         r_decalsystem_numqueued = 0;
13918 }
13919
13920 extern cvar_t cl_decals_max;
13921 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13922 {
13923         int i;
13924         decalsystem_t *decalsystem = &ent->decalsystem;
13925         int numdecals;
13926         int killsequence;
13927         tridecal_t *decal;
13928         float frametime;
13929         float lifetime;
13930
13931         if (!decalsystem->numdecals)
13932                 return;
13933
13934         if (r_showsurfaces.integer)
13935                 return;
13936
13937         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13938         {
13939                 R_DecalSystem_Reset(decalsystem);
13940                 return;
13941         }
13942
13943         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13944         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13945
13946         if (decalsystem->lastupdatetime)
13947                 frametime = (cl.time - decalsystem->lastupdatetime);
13948         else
13949                 frametime = 0;
13950         decalsystem->lastupdatetime = cl.time;
13951         decal = decalsystem->decals;
13952         numdecals = decalsystem->numdecals;
13953
13954         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13955         {
13956                 if (decal->color4ub[0][3])
13957                 {
13958                         decal->lived += frametime;
13959                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13960                         {
13961                                 memset(decal, 0, sizeof(*decal));
13962                                 if (decalsystem->freedecal > i)
13963                                         decalsystem->freedecal = i;
13964                         }
13965                 }
13966         }
13967         decal = decalsystem->decals;
13968         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13969                 numdecals--;
13970
13971         // collapse the array by shuffling the tail decals into the gaps
13972         for (;;)
13973         {
13974                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13975                         decalsystem->freedecal++;
13976                 if (decalsystem->freedecal == numdecals)
13977                         break;
13978                 decal[decalsystem->freedecal] = decal[--numdecals];
13979         }
13980
13981         decalsystem->numdecals = numdecals;
13982
13983         if (numdecals <= 0)
13984         {
13985                 // if there are no decals left, reset decalsystem
13986                 R_DecalSystem_Reset(decalsystem);
13987         }
13988 }
13989
13990 extern skinframe_t *decalskinframe;
13991 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13992 {
13993         int i;
13994         decalsystem_t *decalsystem = &ent->decalsystem;
13995         int numdecals;
13996         tridecal_t *decal;
13997         float faderate;
13998         float alpha;
13999         float *v3f;
14000         float *c4f;
14001         float *t2f;
14002         const int *e;
14003         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14004         int numtris = 0;
14005
14006         numdecals = decalsystem->numdecals;
14007         if (!numdecals)
14008                 return;
14009
14010         if (r_showsurfaces.integer)
14011                 return;
14012
14013         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14014         {
14015                 R_DecalSystem_Reset(decalsystem);
14016                 return;
14017         }
14018
14019         // if the model is static it doesn't matter what value we give for
14020         // wantnormals and wanttangents, so this logic uses only rules applicable
14021         // to a model, knowing that they are meaningless otherwise
14022         if (ent == r_refdef.scene.worldentity)
14023                 RSurf_ActiveWorldEntity();
14024         else
14025                 RSurf_ActiveModelEntity(ent, false, false, false);
14026
14027         decalsystem->lastupdatetime = cl.time;
14028         decal = decalsystem->decals;
14029
14030         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14031
14032         // update vertex positions for animated models
14033         v3f = decalsystem->vertex3f;
14034         c4f = decalsystem->color4f;
14035         t2f = decalsystem->texcoord2f;
14036         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14037         {
14038                 if (!decal->color4ub[0][3])
14039                         continue;
14040
14041                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14042                         continue;
14043
14044                 // update color values for fading decals
14045                 if (decal->lived >= cl_decals_time.value)
14046                 {
14047                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14048                         alpha *= (1.0f/255.0f);
14049                 }
14050                 else
14051                         alpha = 1.0f/255.0f;
14052
14053                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14054                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14055                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14056                 c4f[ 3] = 1;
14057                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14058                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14059                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14060                 c4f[ 7] = 1;
14061                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14062                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14063                 c4f[10] = decal->color4ub[2][2] * alpha;
14064                 c4f[11] = 1;
14065
14066                 t2f[0] = decal->texcoord2f[0][0];
14067                 t2f[1] = decal->texcoord2f[0][1];
14068                 t2f[2] = decal->texcoord2f[1][0];
14069                 t2f[3] = decal->texcoord2f[1][1];
14070                 t2f[4] = decal->texcoord2f[2][0];
14071                 t2f[5] = decal->texcoord2f[2][1];
14072
14073                 // update vertex positions for animated models
14074                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14075                 {
14076                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14077                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14078                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14079                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14080                 }
14081                 else
14082                 {
14083                         VectorCopy(decal->vertex3f[0], v3f);
14084                         VectorCopy(decal->vertex3f[1], v3f + 3);
14085                         VectorCopy(decal->vertex3f[2], v3f + 6);
14086                 }
14087
14088                 if (r_refdef.fogenabled)
14089                 {
14090                         alpha = RSurf_FogVertex(v3f);
14091                         VectorScale(c4f, alpha, c4f);
14092                         alpha = RSurf_FogVertex(v3f + 3);
14093                         VectorScale(c4f + 4, alpha, c4f + 4);
14094                         alpha = RSurf_FogVertex(v3f + 6);
14095                         VectorScale(c4f + 8, alpha, c4f + 8);
14096                 }
14097
14098                 v3f += 9;
14099                 c4f += 12;
14100                 t2f += 6;
14101                 numtris++;
14102         }
14103
14104         if (numtris > 0)
14105         {
14106                 r_refdef.stats.drawndecals += numtris;
14107
14108                 // now render the decals all at once
14109                 // (this assumes they all use one particle font texture!)
14110                 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);
14111 //              R_Mesh_ResetTextureState();
14112                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14113                 GL_DepthMask(false);
14114                 GL_DepthRange(0, 1);
14115                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14116                 GL_DepthTest(true);
14117                 GL_CullFace(GL_NONE);
14118                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14119                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14120                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14121         }
14122 }
14123
14124 static void R_DrawModelDecals(void)
14125 {
14126         int i, numdecals;
14127
14128         // fade faster when there are too many decals
14129         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14130         for (i = 0;i < r_refdef.scene.numentities;i++)
14131                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14132
14133         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14134         for (i = 0;i < r_refdef.scene.numentities;i++)
14135                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14136                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14137
14138         R_DecalSystem_ApplySplatEntitiesQueue();
14139
14140         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14141         for (i = 0;i < r_refdef.scene.numentities;i++)
14142                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14143
14144         r_refdef.stats.totaldecals += numdecals;
14145
14146         if (r_showsurfaces.integer)
14147                 return;
14148
14149         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14150
14151         for (i = 0;i < r_refdef.scene.numentities;i++)
14152         {
14153                 if (!r_refdef.viewcache.entityvisible[i])
14154                         continue;
14155                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14156                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14157         }
14158 }
14159
14160 extern cvar_t mod_collision_bih;
14161 void R_DrawDebugModel(void)
14162 {
14163         entity_render_t *ent = rsurface.entity;
14164         int i, j, k, l, flagsmask;
14165         const msurface_t *surface;
14166         dp_model_t *model = ent->model;
14167         vec3_t v;
14168
14169         switch(vid.renderpath)
14170         {
14171         case RENDERPATH_GL11:
14172         case RENDERPATH_GL13:
14173         case RENDERPATH_GL20:
14174         case RENDERPATH_CGGL:
14175                 break;
14176         case RENDERPATH_D3D9:
14177                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14178                 return;
14179         case RENDERPATH_D3D10:
14180                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14181                 return;
14182         case RENDERPATH_D3D11:
14183                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14184                 return;
14185         }
14186
14187         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14188
14189 //      R_Mesh_ResetTextureState();
14190         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14191         GL_DepthRange(0, 1);
14192         GL_DepthTest(!r_showdisabledepthtest.integer);
14193         GL_DepthMask(false);
14194         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14195
14196         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14197         {
14198                 int triangleindex;
14199                 int bihleafindex;
14200                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14201                 const q3mbrush_t *brush;
14202                 const bih_t *bih = &model->collision_bih;
14203                 const bih_leaf_t *bihleaf;
14204                 float vertex3f[3][3];
14205                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14206                 cullbox = false;
14207                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14208                 {
14209                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14210                                 continue;
14211                         switch (bihleaf->type)
14212                         {
14213                         case BIH_BRUSH:
14214                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14215                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14216                                 {
14217                                         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);
14218                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14219                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14220                                 }
14221                                 break;
14222                         case BIH_COLLISIONTRIANGLE:
14223                                 triangleindex = bihleaf->itemindex;
14224                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14225                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14226                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14227                                 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);
14228                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14229                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14230                                 break;
14231                         case BIH_RENDERTRIANGLE:
14232                                 triangleindex = bihleaf->itemindex;
14233                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14234                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14235                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14236                                 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);
14237                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14238                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14239                                 break;
14240                         }
14241                 }
14242         }
14243
14244         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14245
14246         if (r_showtris.integer || r_shownormals.integer)
14247         {
14248                 if (r_showdisabledepthtest.integer)
14249                 {
14250                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14251                         GL_DepthMask(false);
14252                 }
14253                 else
14254                 {
14255                         GL_BlendFunc(GL_ONE, GL_ZERO);
14256                         GL_DepthMask(true);
14257                 }
14258                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14259                 {
14260                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14261                                 continue;
14262                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14263                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14264                         {
14265                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14266                                 if (r_showtris.value > 0)
14267                                 {
14268                                         if (!rsurface.texture->currentlayers->depthmask)
14269                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14270                                         else if (ent == r_refdef.scene.worldentity)
14271                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14272                                         else
14273                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14274                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14275                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14276                                         RSurf_DrawBatch();
14277                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14278                                         CHECKGLERROR
14279                                 }
14280                                 if (r_shownormals.value < 0)
14281                                 {
14282                                         qglBegin(GL_LINES);
14283                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14284                                         {
14285                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14286                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14287                                                 qglVertex3f(v[0], v[1], v[2]);
14288                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14289                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14290                                                 qglVertex3f(v[0], v[1], v[2]);
14291                                         }
14292                                         qglEnd();
14293                                         CHECKGLERROR
14294                                 }
14295                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14296                                 {
14297                                         qglBegin(GL_LINES);
14298                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14299                                         {
14300                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14301                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14302                                                 qglVertex3f(v[0], v[1], v[2]);
14303                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14304                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14305                                                 qglVertex3f(v[0], v[1], v[2]);
14306                                         }
14307                                         qglEnd();
14308                                         CHECKGLERROR
14309                                         qglBegin(GL_LINES);
14310                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14311                                         {
14312                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14313                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14314                                                 qglVertex3f(v[0], v[1], v[2]);
14315                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14316                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14317                                                 qglVertex3f(v[0], v[1], v[2]);
14318                                         }
14319                                         qglEnd();
14320                                         CHECKGLERROR
14321                                         qglBegin(GL_LINES);
14322                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14323                                         {
14324                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14325                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14326                                                 qglVertex3f(v[0], v[1], v[2]);
14327                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14328                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14329                                                 qglVertex3f(v[0], v[1], v[2]);
14330                                         }
14331                                         qglEnd();
14332                                         CHECKGLERROR
14333                                 }
14334                         }
14335                 }
14336                 rsurface.texture = NULL;
14337         }
14338 }
14339
14340 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14341 int r_maxsurfacelist = 0;
14342 const msurface_t **r_surfacelist = NULL;
14343 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14344 {
14345         int i, j, endj, flagsmask;
14346         dp_model_t *model = r_refdef.scene.worldmodel;
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         RSurf_ActiveWorldEntity();
14362
14363         surfaces = model->data_surfaces;
14364         update = model->brushq1.lightmapupdateflags;
14365
14366         // update light styles on this submodel
14367         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14368         {
14369                 model_brush_lightstyleinfo_t *style;
14370                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14371                 {
14372                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14373                         {
14374                                 int *list = style->surfacelist;
14375                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14376                                 for (j = 0;j < style->numsurfaces;j++)
14377                                         update[list[j]] = true;
14378                         }
14379                 }
14380         }
14381
14382         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14383
14384         if (debug)
14385         {
14386                 R_DrawDebugModel();
14387                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14388                 return;
14389         }
14390
14391         rsurface.lightmaptexture = NULL;
14392         rsurface.deluxemaptexture = NULL;
14393         rsurface.uselightmaptexture = false;
14394         rsurface.texture = NULL;
14395         rsurface.rtlight = NULL;
14396         numsurfacelist = 0;
14397         // add visible surfaces to draw list
14398         for (i = 0;i < model->nummodelsurfaces;i++)
14399         {
14400                 j = model->sortedmodelsurfaces[i];
14401                 if (r_refdef.viewcache.world_surfacevisible[j])
14402                         r_surfacelist[numsurfacelist++] = surfaces + j;
14403         }
14404         // update lightmaps if needed
14405         if (model->brushq1.firstrender)
14406         {
14407                 model->brushq1.firstrender = false;
14408                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14409                         if (update[j])
14410                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14411         }
14412         else if (update)
14413         {
14414                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14415                         if (r_refdef.viewcache.world_surfacevisible[j])
14416                                 if (update[j])
14417                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14418         }
14419         // don't do anything if there were no surfaces
14420         if (!numsurfacelist)
14421         {
14422                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14423                 return;
14424         }
14425         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14426         GL_AlphaTest(false);
14427
14428         // add to stats if desired
14429         if (r_speeds.integer && !skysurfaces && !depthonly)
14430         {
14431                 r_refdef.stats.world_surfaces += numsurfacelist;
14432                 for (j = 0;j < numsurfacelist;j++)
14433                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14434         }
14435
14436         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14437 }
14438
14439 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14440 {
14441         int i, j, endj, flagsmask;
14442         dp_model_t *model = ent->model;
14443         msurface_t *surfaces;
14444         unsigned char *update;
14445         int numsurfacelist = 0;
14446         if (model == NULL)
14447                 return;
14448
14449         if (r_maxsurfacelist < model->num_surfaces)
14450         {
14451                 r_maxsurfacelist = model->num_surfaces;
14452                 if (r_surfacelist)
14453                         Mem_Free((msurface_t **)r_surfacelist);
14454                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14455         }
14456
14457         // if the model is static it doesn't matter what value we give for
14458         // wantnormals and wanttangents, so this logic uses only rules applicable
14459         // to a model, knowing that they are meaningless otherwise
14460         if (ent == r_refdef.scene.worldentity)
14461                 RSurf_ActiveWorldEntity();
14462         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14463                 RSurf_ActiveModelEntity(ent, false, false, false);
14464         else if (prepass)
14465                 RSurf_ActiveModelEntity(ent, true, true, true);
14466         else if (depthonly)
14467         {
14468                 switch (vid.renderpath)
14469                 {
14470                 case RENDERPATH_GL20:
14471                 case RENDERPATH_CGGL:
14472                 case RENDERPATH_D3D9:
14473                 case RENDERPATH_D3D10:
14474                 case RENDERPATH_D3D11:
14475                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14476                         break;
14477                 case RENDERPATH_GL13:
14478                 case RENDERPATH_GL11:
14479                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14480                         break;
14481                 }
14482         }
14483         else
14484         {
14485                 switch (vid.renderpath)
14486                 {
14487                 case RENDERPATH_GL20:
14488                 case RENDERPATH_CGGL:
14489                 case RENDERPATH_D3D9:
14490                 case RENDERPATH_D3D10:
14491                 case RENDERPATH_D3D11:
14492                         RSurf_ActiveModelEntity(ent, true, true, false);
14493                         break;
14494                 case RENDERPATH_GL13:
14495                 case RENDERPATH_GL11:
14496                         RSurf_ActiveModelEntity(ent, true, false, false);
14497                         break;
14498                 }
14499         }
14500
14501         surfaces = model->data_surfaces;
14502         update = model->brushq1.lightmapupdateflags;
14503
14504         // update light styles
14505         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14506         {
14507                 model_brush_lightstyleinfo_t *style;
14508                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14509                 {
14510                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14511                         {
14512                                 int *list = style->surfacelist;
14513                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14514                                 for (j = 0;j < style->numsurfaces;j++)
14515                                         update[list[j]] = true;
14516                         }
14517                 }
14518         }
14519
14520         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14521
14522         if (debug)
14523         {
14524                 R_DrawDebugModel();
14525                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14526                 return;
14527         }
14528
14529         rsurface.lightmaptexture = NULL;
14530         rsurface.deluxemaptexture = NULL;
14531         rsurface.uselightmaptexture = false;
14532         rsurface.texture = NULL;
14533         rsurface.rtlight = NULL;
14534         numsurfacelist = 0;
14535         // add visible surfaces to draw list
14536         for (i = 0;i < model->nummodelsurfaces;i++)
14537                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14538         // don't do anything if there were no surfaces
14539         if (!numsurfacelist)
14540         {
14541                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14542                 return;
14543         }
14544         // update lightmaps if needed
14545         if (update)
14546         {
14547                 int updated = 0;
14548                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14549                 {
14550                         if (update[j])
14551                         {
14552                                 updated++;
14553                                 R_BuildLightMap(ent, surfaces + j);
14554                         }
14555                 }
14556         }
14557         if (update)
14558                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14559                         if (update[j])
14560                                 R_BuildLightMap(ent, surfaces + j);
14561         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14562         GL_AlphaTest(false);
14563
14564         // add to stats if desired
14565         if (r_speeds.integer && !skysurfaces && !depthonly)
14566         {
14567                 r_refdef.stats.entities_surfaces += numsurfacelist;
14568                 for (j = 0;j < numsurfacelist;j++)
14569                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14570         }
14571
14572         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14573 }
14574
14575 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14576 {
14577         static texture_t texture;
14578         static msurface_t surface;
14579         const msurface_t *surfacelist = &surface;
14580
14581         // fake enough texture and surface state to render this geometry
14582
14583         texture.update_lastrenderframe = -1; // regenerate this texture
14584         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14585         texture.currentskinframe = skinframe;
14586         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14587         texture.offsetmapping = OFFSETMAPPING_OFF;
14588         texture.offsetscale = 1;
14589         texture.specularscalemod = 1;
14590         texture.specularpowermod = 1;
14591
14592         surface.texture = &texture;
14593         surface.num_triangles = numtriangles;
14594         surface.num_firsttriangle = firsttriangle;
14595         surface.num_vertices = numvertices;
14596         surface.num_firstvertex = firstvertex;
14597
14598         // now render it
14599         rsurface.texture = R_GetCurrentTexture(surface.texture);
14600         rsurface.lightmaptexture = NULL;
14601         rsurface.deluxemaptexture = NULL;
14602         rsurface.uselightmaptexture = false;
14603         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14604 }
14605
14606 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)
14607 {
14608         static msurface_t surface;
14609         const msurface_t *surfacelist = &surface;
14610
14611         // fake enough texture and surface state to render this geometry
14612         surface.texture = texture;
14613         surface.num_triangles = numtriangles;
14614         surface.num_firsttriangle = firsttriangle;
14615         surface.num_vertices = numvertices;
14616         surface.num_firstvertex = firstvertex;
14617
14618         // now render it
14619         rsurface.texture = R_GetCurrentTexture(surface.texture);
14620         rsurface.lightmaptexture = NULL;
14621         rsurface.deluxemaptexture = NULL;
14622         rsurface.uselightmaptexture = false;
14623         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14624 }