]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix wateralpha
[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", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
195 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
196
197 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
198 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"};
199
200 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)"};
201
202 extern cvar_t v_glslgamma;
203
204 extern qboolean v_flipped_state;
205
206 static struct r_bloomstate_s
207 {
208         qboolean enabled;
209         qboolean hdr;
210
211         int bloomwidth, bloomheight;
212
213         int screentexturewidth, screentextureheight;
214         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
215
216         int bloomtexturewidth, bloomtextureheight;
217         rtexture_t *texture_bloom;
218
219         // arrays for rendering the screen passes
220         float screentexcoord2f[8];
221         float bloomtexcoord2f[8];
222         float offsettexcoord2f[8];
223
224         r_viewport_t viewport;
225 }
226 r_bloomstate;
227
228 r_waterstate_t r_waterstate;
229
230 /// shadow volume bsp struct with automatically growing nodes buffer
231 svbsp_t r_svbsp;
232
233 rtexture_t *r_texture_blanknormalmap;
234 rtexture_t *r_texture_white;
235 rtexture_t *r_texture_grey128;
236 rtexture_t *r_texture_black;
237 rtexture_t *r_texture_notexture;
238 rtexture_t *r_texture_whitecube;
239 rtexture_t *r_texture_normalizationcube;
240 rtexture_t *r_texture_fogattenuation;
241 rtexture_t *r_texture_fogheighttexture;
242 rtexture_t *r_texture_gammaramps;
243 unsigned int r_texture_gammaramps_serial;
244 //rtexture_t *r_texture_fogintensity;
245 rtexture_t *r_texture_reflectcube;
246
247 // TODO: hash lookups?
248 typedef struct cubemapinfo_s
249 {
250         char basename[64];
251         rtexture_t *texture;
252 }
253 cubemapinfo_t;
254
255 int r_texture_numcubemaps;
256 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
257
258 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
259 unsigned int r_numqueries;
260 unsigned int r_maxqueries;
261
262 typedef struct r_qwskincache_s
263 {
264         char name[MAX_QPATH];
265         skinframe_t *skinframe;
266 }
267 r_qwskincache_t;
268
269 static r_qwskincache_t *r_qwskincache;
270 static int r_qwskincache_size;
271
272 /// vertex coordinates for a quad that covers the screen exactly
273 extern const float r_screenvertex3f[12];
274 extern const float r_d3dscreenvertex3f[12];
275 const float r_screenvertex3f[12] =
276 {
277         0, 0, 0,
278         1, 0, 0,
279         1, 1, 0,
280         0, 1, 0
281 };
282 const float r_d3dscreenvertex3f[12] =
283 {
284         0, 1, 0,
285         1, 1, 0,
286         1, 0, 0,
287         0, 0, 0
288 };
289
290 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
291 {
292         int i;
293         for (i = 0;i < verts;i++)
294         {
295                 out[0] = in[0] * r;
296                 out[1] = in[1] * g;
297                 out[2] = in[2] * b;
298                 out[3] = in[3];
299                 in += 4;
300                 out += 4;
301         }
302 }
303
304 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
305 {
306         int i;
307         for (i = 0;i < verts;i++)
308         {
309                 out[0] = r;
310                 out[1] = g;
311                 out[2] = b;
312                 out[3] = a;
313                 out += 4;
314         }
315 }
316
317 // FIXME: move this to client?
318 void FOG_clear(void)
319 {
320         if (gamemode == GAME_NEHAHRA)
321         {
322                 Cvar_Set("gl_fogenable", "0");
323                 Cvar_Set("gl_fogdensity", "0.2");
324                 Cvar_Set("gl_fogred", "0.3");
325                 Cvar_Set("gl_foggreen", "0.3");
326                 Cvar_Set("gl_fogblue", "0.3");
327         }
328         r_refdef.fog_density = 0;
329         r_refdef.fog_red = 0;
330         r_refdef.fog_green = 0;
331         r_refdef.fog_blue = 0;
332         r_refdef.fog_alpha = 1;
333         r_refdef.fog_start = 0;
334         r_refdef.fog_end = 16384;
335         r_refdef.fog_height = 1<<30;
336         r_refdef.fog_fadedepth = 128;
337         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
338 }
339
340 static void R_BuildBlankTextures(void)
341 {
342         unsigned char data[4];
343         data[2] = 128; // normal X
344         data[1] = 128; // normal Y
345         data[0] = 255; // normal Z
346         data[3] = 128; // height
347         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
348         data[0] = 255;
349         data[1] = 255;
350         data[2] = 255;
351         data[3] = 255;
352         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 128;
354         data[1] = 128;
355         data[2] = 128;
356         data[3] = 255;
357         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 0;
359         data[1] = 0;
360         data[2] = 0;
361         data[3] = 255;
362         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 }
364
365 static void R_BuildNoTexture(void)
366 {
367         int x, y;
368         unsigned char pix[16][16][4];
369         // this makes a light grey/dark grey checkerboard texture
370         for (y = 0;y < 16;y++)
371         {
372                 for (x = 0;x < 16;x++)
373                 {
374                         if ((y < 8) ^ (x < 8))
375                         {
376                                 pix[y][x][0] = 128;
377                                 pix[y][x][1] = 128;
378                                 pix[y][x][2] = 128;
379                                 pix[y][x][3] = 255;
380                         }
381                         else
382                         {
383                                 pix[y][x][0] = 64;
384                                 pix[y][x][1] = 64;
385                                 pix[y][x][2] = 64;
386                                 pix[y][x][3] = 255;
387                         }
388                 }
389         }
390         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildWhiteCube(void)
394 {
395         unsigned char data[6*1*1*4];
396         memset(data, 255, sizeof(data));
397         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildNormalizationCube(void)
401 {
402         int x, y, side;
403         vec3_t v;
404         vec_t s, t, intensity;
405 #define NORMSIZE 64
406         unsigned char *data;
407         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
408         for (side = 0;side < 6;side++)
409         {
410                 for (y = 0;y < NORMSIZE;y++)
411                 {
412                         for (x = 0;x < NORMSIZE;x++)
413                         {
414                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
415                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 switch(side)
417                                 {
418                                 default:
419                                 case 0:
420                                         v[0] = 1;
421                                         v[1] = -t;
422                                         v[2] = -s;
423                                         break;
424                                 case 1:
425                                         v[0] = -1;
426                                         v[1] = -t;
427                                         v[2] = s;
428                                         break;
429                                 case 2:
430                                         v[0] = s;
431                                         v[1] = 1;
432                                         v[2] = t;
433                                         break;
434                                 case 3:
435                                         v[0] = s;
436                                         v[1] = -1;
437                                         v[2] = -t;
438                                         break;
439                                 case 4:
440                                         v[0] = s;
441                                         v[1] = -t;
442                                         v[2] = 1;
443                                         break;
444                                 case 5:
445                                         v[0] = -s;
446                                         v[1] = -t;
447                                         v[2] = -1;
448                                         break;
449                                 }
450                                 intensity = 127.0f / sqrt(DotProduct(v, v));
451                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
452                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
453                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
454                                 data[((side*64+y)*64+x)*4+3] = 255;
455                         }
456                 }
457         }
458         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
459         Mem_Free(data);
460 }
461
462 static void R_BuildFogTexture(void)
463 {
464         int x, b;
465 #define FOGWIDTH 256
466         unsigned char data1[FOGWIDTH][4];
467         //unsigned char data2[FOGWIDTH][4];
468         double d, r, alpha;
469
470         r_refdef.fogmasktable_start = r_refdef.fog_start;
471         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
472         r_refdef.fogmasktable_range = r_refdef.fogrange;
473         r_refdef.fogmasktable_density = r_refdef.fog_density;
474
475         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
476         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
477         {
478                 d = (x * r - r_refdef.fogmasktable_start);
479                 if(developer_extra.integer)
480                         Con_DPrintf("%f ", d);
481                 d = max(0, d);
482                 if (r_fog_exp2.integer)
483                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
484                 else
485                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
486                 if(developer_extra.integer)
487                         Con_DPrintf(" : %f ", alpha);
488                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
489                 if(developer_extra.integer)
490                         Con_DPrintf(" = %f\n", alpha);
491                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
492         }
493
494         for (x = 0;x < FOGWIDTH;x++)
495         {
496                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
497                 data1[x][0] = b;
498                 data1[x][1] = b;
499                 data1[x][2] = b;
500                 data1[x][3] = 255;
501                 //data2[x][0] = 255 - b;
502                 //data2[x][1] = 255 - b;
503                 //data2[x][2] = 255 - b;
504                 //data2[x][3] = 255;
505         }
506         if (r_texture_fogattenuation)
507         {
508                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
509                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
510         }
511         else
512         {
513                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
514                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
515         }
516 }
517
518 static void R_BuildFogHeightTexture(void)
519 {
520         unsigned char *inpixels;
521         int size;
522         int x;
523         int y;
524         int j;
525         float c[4];
526         float f;
527         inpixels = NULL;
528         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
529         if (r_refdef.fogheighttexturename[0])
530                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
531         if (!inpixels)
532         {
533                 r_refdef.fog_height_tablesize = 0;
534                 if (r_texture_fogheighttexture)
535                         R_FreeTexture(r_texture_fogheighttexture);
536                 r_texture_fogheighttexture = NULL;
537                 if (r_refdef.fog_height_table2d)
538                         Mem_Free(r_refdef.fog_height_table2d);
539                 r_refdef.fog_height_table2d = NULL;
540                 if (r_refdef.fog_height_table1d)
541                         Mem_Free(r_refdef.fog_height_table1d);
542                 r_refdef.fog_height_table1d = NULL;
543                 return;
544         }
545         size = image_width;
546         r_refdef.fog_height_tablesize = size;
547         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
548         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
549         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
550         Mem_Free(inpixels);
551         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
552         // average fog color table accounting for every fog layer between a point
553         // and the camera.  (Note: attenuation is handled separately!)
554         for (y = 0;y < size;y++)
555         {
556                 for (x = 0;x < size;x++)
557                 {
558                         Vector4Clear(c);
559                         f = 0;
560                         if (x < y)
561                         {
562                                 for (j = x;j <= y;j++)
563                                 {
564                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
565                                         f++;
566                                 }
567                         }
568                         else
569                         {
570                                 for (j = x;j >= y;j--)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         f = 1.0f / f;
577                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
581                 }
582         }
583         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
584 }
585
586 //=======================================================================================================================================================
587
588 static const char *builtinshaderstring =
589 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
590 "// written by Forest 'LordHavoc' Hale\n"
591 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
592 "\n"
593 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
594 "# define USEFOG\n"
595 "#endif\n"
596 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
597 "#define USELIGHTMAP\n"
598 "#endif\n"
599 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
600 "#define USEEYEVECTOR\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USESHADOWMAP2D\n"
604 "# ifdef GL_EXT_gpu_shader4\n"
605 "#   extension GL_EXT_gpu_shader4 : enable\n"
606 "# endif\n"
607 "# ifdef GL_ARB_texture_gather\n"
608 "#   extension GL_ARB_texture_gather : enable\n"
609 "# else\n"
610 "#   ifdef GL_AMD_texture_texture4\n"
611 "#     extension GL_AMD_texture_texture4 : enable\n"
612 "#   endif\n"
613 "# endif\n"
614 "#endif\n"
615 "\n"
616 "//#ifdef USESHADOWSAMPLER\n"
617 "//# extension GL_ARB_shadow : enable\n"
618 "//#endif\n"
619 "\n"
620 "//#ifdef __GLSL_CG_DATA_TYPES\n"
621 "//# define myhalf half\n"
622 "//# define myhalf2 half2\n"
623 "//# define myhalf3 half3\n"
624 "//# define myhalf4 half4\n"
625 "//#else\n"
626 "# define myhalf float\n"
627 "# define myhalf2 vec2\n"
628 "# define myhalf3 vec3\n"
629 "# define myhalf4 vec4\n"
630 "//#endif\n"
631 "\n"
632 "#ifdef VERTEX_SHADER\n"
633 "uniform mat4 ModelViewProjectionMatrix;\n"
634 "#endif\n"
635 "\n"
636 "#ifdef MODE_DEPTH_OR_SHADOW\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
641 "}\n"
642 "#endif\n"
643 "#else // !MODE_DEPTH_ORSHADOW\n"
644 "\n"
645 "\n"
646 "\n"
647 "\n"
648 "#ifdef MODE_SHOWDEPTH\n"
649 "#ifdef VERTEX_SHADER\n"
650 "void main(void)\n"
651 "{\n"
652 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
653 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
654 "}\n"
655 "#endif\n"
656 "\n"
657 "#ifdef FRAGMENT_SHADER\n"
658 "void main(void)\n"
659 "{\n"
660 "       gl_FragColor = gl_Color;\n"
661 "}\n"
662 "#endif\n"
663 "#else // !MODE_SHOWDEPTH\n"
664 "\n"
665 "\n"
666 "\n"
667 "\n"
668 "#ifdef MODE_POSTPROCESS\n"
669 "varying vec2 TexCoord1;\n"
670 "varying vec2 TexCoord2;\n"
671 "\n"
672 "#ifdef VERTEX_SHADER\n"
673 "void main(void)\n"
674 "{\n"
675 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
676 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
677 "#ifdef USEBLOOM\n"
678 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
679 "#endif\n"
680 "}\n"
681 "#endif\n"
682 "\n"
683 "#ifdef FRAGMENT_SHADER\n"
684 "uniform sampler2D Texture_First;\n"
685 "#ifdef USEBLOOM\n"
686 "uniform sampler2D Texture_Second;\n"
687 "uniform vec4 BloomColorSubtract;\n"
688 "#endif\n"
689 "#ifdef USEGAMMARAMPS\n"
690 "uniform sampler2D Texture_GammaRamps;\n"
691 "#endif\n"
692 "#ifdef USESATURATION\n"
693 "uniform float Saturation;\n"
694 "#endif\n"
695 "#ifdef USEVIEWTINT\n"
696 "uniform vec4 ViewTintColor;\n"
697 "#endif\n"
698 "//uncomment these if you want to use them:\n"
699 "uniform vec4 UserVec1;\n"
700 "uniform vec4 UserVec2;\n"
701 "// uniform vec4 UserVec3;\n"
702 "// uniform vec4 UserVec4;\n"
703 "// uniform float ClientTime;\n"
704 "uniform vec2 PixelSize;\n"
705 "void main(void)\n"
706 "{\n"
707 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
708 "#ifdef USEBLOOM\n"
709 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
710 "#endif\n"
711 "#ifdef USEVIEWTINT\n"
712 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
713 "#endif\n"
714 "\n"
715 "#ifdef USEPOSTPROCESSING\n"
716 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
717 "// 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"
718 "       float sobel = 1.0;\n"
719 "       // vec2 ts = textureSize(Texture_First, 0);\n"
720 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
721 "       vec2 px = PixelSize;\n"
722 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
723 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
724 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
727 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
728 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
730 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
731 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
732 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
733 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
734 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
735 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
736 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
737 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
738 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
739 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
740 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
741 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
742 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
743 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
744 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
745 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
746 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
752 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
753 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
754 "#endif\n"
755 "\n"
756 "#ifdef USESATURATION\n"
757 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
758 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
759 "       // 'vampire sight' effect, wheres red is compensated\n"
760 "       #ifdef SATURATION_REDCOMPENSATE\n"
761 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
762 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
763 "               gl_FragColor.r += rboost;\n"
764 "       #else\n"
765 "               // normal desaturation\n"
766 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
767 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
768 "       #endif\n"
769 "#endif\n"
770 "\n"
771 "#ifdef USEGAMMARAMPS\n"
772 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
773 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
774 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
775 "#endif\n"
776 "}\n"
777 "#endif\n"
778 "#else // !MODE_POSTPROCESS\n"
779 "\n"
780 "\n"
781 "\n"
782 "\n"
783 "#ifdef MODE_GENERIC\n"
784 "#ifdef USEDIFFUSE\n"
785 "varying vec2 TexCoord1;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "varying vec2 TexCoord2;\n"
789 "#endif\n"
790 "#ifdef VERTEX_SHADER\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FrontColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
796 "#endif\n"
797 "#ifdef USESPECULAR\n"
798 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
799 "#endif\n"
800 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
801 "}\n"
802 "#endif\n"
803 "\n"
804 "#ifdef FRAGMENT_SHADER\n"
805 "#ifdef USEDIFFUSE\n"
806 "uniform sampler2D Texture_First;\n"
807 "#endif\n"
808 "#ifdef USESPECULAR\n"
809 "uniform sampler2D Texture_Second;\n"
810 "#endif\n"
811 "\n"
812 "void main(void)\n"
813 "{\n"
814 "#ifdef USEVIEWTINT\n"
815 "       gl_FragColor = gl_Color;\n"
816 "#else\n"
817 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
818 "#endif\n"
819 "#ifdef USEDIFFUSE\n"
820 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
821 "#endif\n"
822 "\n"
823 "#ifdef USESPECULAR\n"
824 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
825 "# ifdef USECOLORMAPPING\n"
826 "       gl_FragColor *= tex2;\n"
827 "# endif\n"
828 "# ifdef USEGLOW\n"
829 "       gl_FragColor += tex2;\n"
830 "# endif\n"
831 "# ifdef USEVERTEXTEXTUREBLEND\n"
832 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
833 "# endif\n"
834 "#endif\n"
835 "}\n"
836 "#endif\n"
837 "#else // !MODE_GENERIC\n"
838 "\n"
839 "\n"
840 "\n"
841 "\n"
842 "#ifdef MODE_BLOOMBLUR\n"
843 "varying TexCoord;\n"
844 "#ifdef VERTEX_SHADER\n"
845 "void main(void)\n"
846 "{\n"
847 "       gl_FrontColor = gl_Color;\n"
848 "       TexCoord = gl_MultiTexCoord0.xy;\n"
849 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
850 "}\n"
851 "#endif\n"
852 "\n"
853 "#ifdef FRAGMENT_SHADER\n"
854 "uniform sampler2D Texture_First;\n"
855 "uniform vec4 BloomBlur_Parameters;\n"
856 "\n"
857 "void main(void)\n"
858 "{\n"
859 "       int i;\n"
860 "       vec2 tc = TexCoord;\n"
861 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
862 "       tc += BloomBlur_Parameters.xy;\n"
863 "       for (i = 1;i < SAMPLES;i++)\n"
864 "       {\n"
865 "               color += texture2D(Texture_First, tc).rgb;\n"
866 "               tc += BloomBlur_Parameters.xy;\n"
867 "       }\n"
868 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
869 "}\n"
870 "#endif\n"
871 "#else // !MODE_BLOOMBLUR\n"
872 "#ifdef MODE_REFRACTION\n"
873 "varying vec2 TexCoord;\n"
874 "varying vec4 ModelViewProjectionPosition;\n"
875 "uniform mat4 TexMatrix;\n"
876 "#ifdef VERTEX_SHADER\n"
877 "\n"
878 "void main(void)\n"
879 "{\n"
880 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
881 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
882 "       ModelViewProjectionPosition = gl_Position;\n"
883 "}\n"
884 "#endif\n"
885 "\n"
886 "#ifdef FRAGMENT_SHADER\n"
887 "uniform sampler2D Texture_Normal;\n"
888 "uniform sampler2D Texture_Refraction;\n"
889 "uniform sampler2D Texture_Reflection;\n"
890 "\n"
891 "uniform vec4 DistortScaleRefractReflect;\n"
892 "uniform vec4 ScreenScaleRefractReflect;\n"
893 "uniform vec4 ScreenCenterRefractReflect;\n"
894 "uniform vec4 RefractColor;\n"
895 "uniform vec4 ReflectColor;\n"
896 "uniform float ReflectFactor;\n"
897 "uniform float ReflectOffset;\n"
898 "\n"
899 "void main(void)\n"
900 "{\n"
901 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
902 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
903 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
905 "       // FIXME temporary hack to detect the case that the reflection\n"
906 "       // gets blackened at edges due to leaving the area that contains actual\n"
907 "       // content.\n"
908 "       // Remove this 'ack once we have a better way to stop this thing from\n"
909 "       // 'appening.\n"
910 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
913 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
914 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
915 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
916 "}\n"
917 "#endif\n"
918 "#else // !MODE_REFRACTION\n"
919 "\n"
920 "\n"
921 "\n"
922 "\n"
923 "#ifdef MODE_WATER\n"
924 "varying vec2 TexCoord;\n"
925 "varying vec3 EyeVector;\n"
926 "varying vec4 ModelViewProjectionPosition;\n"
927 "#ifdef VERTEX_SHADER\n"
928 "uniform vec3 EyePosition;\n"
929 "uniform mat4 TexMatrix;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
934 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
935 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
936 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
937 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
938 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
939 "       ModelViewProjectionPosition = gl_Position;\n"
940 "}\n"
941 "#endif\n"
942 "\n"
943 "#ifdef FRAGMENT_SHADER\n"
944 "uniform sampler2D Texture_Normal;\n"
945 "uniform sampler2D Texture_Refraction;\n"
946 "uniform sampler2D Texture_Reflection;\n"
947 "\n"
948 "uniform vec4 DistortScaleRefractReflect;\n"
949 "uniform vec4 ScreenScaleRefractReflect;\n"
950 "uniform vec4 ScreenCenterRefractReflect;\n"
951 "uniform vec4 RefractColor;\n"
952 "uniform vec4 ReflectColor;\n"
953 "uniform float ReflectFactor;\n"
954 "uniform float ReflectOffset;\n"
955 "uniform float ClientTime;\n"
956 "#ifdef USENORMALMAPSCROLLBLEND\n"
957 "uniform vec2 NormalmapScrollBlend;\n"
958 "#endif\n"
959 "\n"
960 "void main(void)\n"
961 "{\n"
962 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
963 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
964 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
966 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
967 "       #ifdef USENORMALMAPSCROLLBLEND\n"
968 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
969 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
970 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
971 "       #else\n"
972 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
973 "       #endif\n"
974 "       // FIXME temporary hack to detect the case that the reflection\n"
975 "       // gets blackened at edges due to leaving the area that contains actual\n"
976 "       // content.\n"
977 "       // Remove this 'ack once we have a better way to stop this thing from\n"
978 "       // 'appening.\n"
979 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
980 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
981 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
982 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
983 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
987 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
988 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
989 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
990 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
991 "}\n"
992 "#endif\n"
993 "#else // !MODE_WATER\n"
994 "\n"
995 "\n"
996 "\n"
997 "\n"
998 "// common definitions between vertex shader and fragment shader:\n"
999 "\n"
1000 "varying vec2 TexCoord;\n"
1001 "#ifdef USEVERTEXTEXTUREBLEND\n"
1002 "varying vec2 TexCoord2;\n"
1003 "#endif\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "varying vec2 TexCoordLightmap;\n"
1006 "#endif\n"
1007 "\n"
1008 "#ifdef MODE_LIGHTSOURCE\n"
1009 "varying vec3 CubeVector;\n"
1010 "#endif\n"
1011 "\n"
1012 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1013 "varying vec3 LightVector;\n"
1014 "#endif\n"
1015 "\n"
1016 "#ifdef USEEYEVECTOR\n"
1017 "varying vec3 EyeVector;\n"
1018 "#endif\n"
1019 "#ifdef USEFOG\n"
1020 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1021 "#endif\n"
1022 "\n"
1023 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1024 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1025 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1026 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1027 "#endif\n"
1028 "\n"
1029 "#ifdef USEREFLECTION\n"
1030 "varying vec4 ModelViewProjectionPosition;\n"
1031 "#endif\n"
1032 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1034 "varying vec4 ModelViewPosition;\n"
1035 "#endif\n"
1036 "\n"
1037 "#ifdef MODE_LIGHTSOURCE\n"
1038 "uniform vec3 LightPosition;\n"
1039 "#endif\n"
1040 "uniform vec3 EyePosition;\n"
1041 "#ifdef MODE_LIGHTDIRECTION\n"
1042 "uniform vec3 LightDir;\n"
1043 "#endif\n"
1044 "uniform vec4 FogPlane;\n"
1045 "\n"
1046 "#ifdef USESHADOWMAPORTHO\n"
1047 "varying vec3 ShadowMapTC;\n"
1048 "#endif\n"
1049 "\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "// 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"
1055 "\n"
1056 "// fragment shader specific:\n"
1057 "#ifdef FRAGMENT_SHADER\n"
1058 "\n"
1059 "uniform sampler2D Texture_Normal;\n"
1060 "uniform sampler2D Texture_Color;\n"
1061 "uniform sampler2D Texture_Gloss;\n"
1062 "#ifdef USEGLOW\n"
1063 "uniform sampler2D Texture_Glow;\n"
1064 "#endif\n"
1065 "#ifdef USEVERTEXTEXTUREBLEND\n"
1066 "uniform sampler2D Texture_SecondaryNormal;\n"
1067 "uniform sampler2D Texture_SecondaryColor;\n"
1068 "uniform sampler2D Texture_SecondaryGloss;\n"
1069 "#ifdef USEGLOW\n"
1070 "uniform sampler2D Texture_SecondaryGlow;\n"
1071 "#endif\n"
1072 "#endif\n"
1073 "#ifdef USECOLORMAPPING\n"
1074 "uniform sampler2D Texture_Pants;\n"
1075 "uniform sampler2D Texture_Shirt;\n"
1076 "#endif\n"
1077 "#ifdef USEFOG\n"
1078 "#ifdef USEFOGHEIGHTTEXTURE\n"
1079 "uniform sampler2D Texture_FogHeightTexture;\n"
1080 "#endif\n"
1081 "uniform sampler2D Texture_FogMask;\n"
1082 "#endif\n"
1083 "#ifdef USELIGHTMAP\n"
1084 "uniform sampler2D Texture_Lightmap;\n"
1085 "#endif\n"
1086 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1087 "uniform sampler2D Texture_Deluxemap;\n"
1088 "#endif\n"
1089 "#ifdef USEREFLECTION\n"
1090 "uniform sampler2D Texture_Reflection;\n"
1091 "#endif\n"
1092 "\n"
1093 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1094 "uniform sampler2D Texture_ScreenDepth;\n"
1095 "uniform sampler2D Texture_ScreenNormalMap;\n"
1096 "#endif\n"
1097 "#ifdef USEDEFERREDLIGHTMAP\n"
1098 "uniform sampler2D Texture_ScreenDiffuse;\n"
1099 "uniform sampler2D Texture_ScreenSpecular;\n"
1100 "#endif\n"
1101 "\n"
1102 "uniform myhalf3 Color_Pants;\n"
1103 "uniform myhalf3 Color_Shirt;\n"
1104 "uniform myhalf3 FogColor;\n"
1105 "\n"
1106 "#ifdef USEFOG\n"
1107 "uniform float FogRangeRecip;\n"
1108 "uniform float FogPlaneViewDist;\n"
1109 "uniform float FogHeightFade;\n"
1110 "vec3 FogVertex(vec3 surfacecolor)\n"
1111 "{\n"
1112 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1113 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1114 "       float fogfrac;\n"
1115 "#ifdef USEFOGHEIGHTTEXTURE\n"
1116 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1117 "       fogfrac = fogheightpixel.a;\n"
1118 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1119 "#else\n"
1120 "# ifdef USEFOGOUTSIDE\n"
1121 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1122 "# else\n"
1123 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1124 "# endif\n"
1125 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1126 "#endif\n"
1127 "}\n"
1128 "#endif\n"
1129 "\n"
1130 "#ifdef USEOFFSETMAPPING\n"
1131 "uniform float OffsetMapping_Scale;\n"
1132 "vec2 OffsetMapping(vec2 TexCoord)\n"
1133 "{\n"
1134 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1135 "       // 14 sample relief mapping: linear search and then binary search\n"
1136 "       // this basically steps forward a small amount repeatedly until it finds\n"
1137 "       // itself inside solid, then jitters forward and back using decreasing\n"
1138 "       // amounts to find the impact\n"
1139 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1140 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1141 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 RT = vec3(TexCoord, 1);\n"
1143 "       OffsetVector *= 0.1;\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);\n"
1153 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1158 "       return RT.xy;\n"
1159 "#else\n"
1160 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1161 "       // this basically moves forward the full distance, and then backs up based\n"
1162 "       // on height of samples\n"
1163 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1164 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1165 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       TexCoord += OffsetVector;\n"
1167 "       OffsetVector *= 0.5;\n"
1168 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       return TexCoord;\n"
1171 "#endif\n"
1172 "}\n"
1173 "#endif // USEOFFSETMAPPING\n"
1174 "\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1176 "uniform sampler2D Texture_Attenuation;\n"
1177 "uniform samplerCube Texture_Cube;\n"
1178 "#endif\n"
1179 "\n"
1180 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1181 "\n"
1182 "#ifdef USESHADOWMAP2D\n"
1183 "# ifdef USESHADOWSAMPLER\n"
1184 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1185 "# else\n"
1186 "uniform sampler2D Texture_ShadowMap2D;\n"
1187 "# endif\n"
1188 "#endif\n"
1189 "\n"
1190 "#ifdef USESHADOWMAPVSDCT\n"
1191 "uniform samplerCube Texture_CubeProjection;\n"
1192 "#endif\n"
1193 "\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "uniform vec2 ShadowMap_TextureScale;\n"
1196 "uniform vec4 ShadowMap_Parameters;\n"
1197 "#endif\n"
1198 "\n"
1199 "#if defined(USESHADOWMAP2D)\n"
1200 "# ifdef USESHADOWMAPORTHO\n"
1201 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1202 "# else\n"
1203 "#  ifdef USESHADOWMAPVSDCT\n"
1204 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1205 "{\n"
1206 "       vec3 adir = abs(dir);\n"
1207 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1208 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1209 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1210 "}\n"
1211 "#  else\n"
1212 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1213 "{\n"
1214 "       vec3 adir = abs(dir);\n"
1215 "       float ma = adir.z;\n"
1216 "       vec4 proj = vec4(dir, 2.5);\n"
1217 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1218 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1219 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1220 "       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"
1221 "}\n"
1222 "#  endif\n"
1223 "# endif\n"
1224 "#endif // defined(USESHADOWMAP2D)\n"
1225 "\n"
1226 "# ifdef USESHADOWMAP2D\n"
1227 "float ShadowMapCompare(vec3 dir)\n"
1228 "{\n"
1229 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1230 "       float f;\n"
1231 "\n"
1232 "#  ifdef USESHADOWSAMPLER\n"
1233 "#    ifdef USESHADOWMAPPCF\n"
1234 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1235 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1236 "       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"
1237 "#    else\n"
1238 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1239 "#    endif\n"
1240 "#  else\n"
1241 "#    ifdef USESHADOWMAPPCF\n"
1242 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1243 "#      ifdef GL_ARB_texture_gather\n"
1244 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1245 "#      else\n"
1246 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1247 "#      endif\n"
1248 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1251 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1252 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1253 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1254 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1255 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1256 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1257 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1258 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1259 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1260 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1261 "       locols.yz += group2.ab;\n"
1262 "       hicols.yz += group8.rg;\n"
1263 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1264 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1265 "                               mix(locols, hicols, offset.y);\n"
1266 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1267 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1268 "       f = dot(cols, vec4(1.0/25.0));\n"
1269 "#      else\n"
1270 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1271 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1272 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1273 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1274 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1275 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1276 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 "#      endif\n"
1278 "#     else\n"
1279 "#      ifdef GL_EXT_gpu_shader4\n"
1280 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1281 "#      else\n"
1282 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1283 "#      endif\n"
1284 "#      if USESHADOWMAPPCF > 1\n"
1285 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1286 "       center *= ShadowMap_TextureScale;\n"
1287 "       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"
1288 "       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"
1289 "       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"
1290 "       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"
1291 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1292 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1293 "#      else\n"
1294 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1295 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1296 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1297 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1298 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1299 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1300 "#      endif\n"
1301 "#     endif\n"
1302 "#    else\n"
1303 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1304 "#    endif\n"
1305 "#  endif\n"
1306 "#  ifdef USESHADOWMAPORTHO\n"
1307 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1308 "#  else\n"
1309 "       return f;\n"
1310 "#  endif\n"
1311 "}\n"
1312 "# endif\n"
1313 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1314 "#endif // FRAGMENT_SHADER\n"
1315 "\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "#ifdef MODE_DEFERREDGEOMETRY\n"
1320 "#ifdef VERTEX_SHADER\n"
1321 "uniform mat4 TexMatrix;\n"
1322 "#ifdef USEVERTEXTEXTUREBLEND\n"
1323 "uniform mat4 BackgroundTexMatrix;\n"
1324 "#endif\n"
1325 "uniform mat4 ModelViewMatrix;\n"
1326 "void main(void)\n"
1327 "{\n"
1328 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1329 "#ifdef USEVERTEXTEXTUREBLEND\n"
1330 "       gl_FrontColor = gl_Color;\n"
1331 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1332 "#endif\n"
1333 "\n"
1334 "       // transform unnormalized eye direction into tangent space\n"
1335 "#ifdef USEOFFSETMAPPING\n"
1336 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1337 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1338 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1339 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1340 "#endif\n"
1341 "\n"
1342 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1343 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1344 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1345 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1346 "}\n"
1347 "#endif // VERTEX_SHADER\n"
1348 "\n"
1349 "#ifdef FRAGMENT_SHADER\n"
1350 "void main(void)\n"
1351 "{\n"
1352 "#ifdef USEOFFSETMAPPING\n"
1353 "       // apply offsetmapping\n"
1354 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1355 "#define TexCoord TexCoordOffset\n"
1356 "#endif\n"
1357 "\n"
1358 "#ifdef USEALPHAKILL\n"
1359 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1360 "               discard;\n"
1361 "#endif\n"
1362 "\n"
1363 "#ifdef USEVERTEXTEXTUREBLEND\n"
1364 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1365 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1366 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1367 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1368 "#endif\n"
1369 "\n"
1370 "#ifdef USEVERTEXTEXTUREBLEND\n"
1371 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1372 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1373 "#else\n"
1374 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1375 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1376 "#endif\n"
1377 "\n"
1378 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1379 "}\n"
1380 "#endif // FRAGMENT_SHADER\n"
1381 "#else // !MODE_DEFERREDGEOMETRY\n"
1382 "\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1387 "#ifdef VERTEX_SHADER\n"
1388 "uniform mat4 ModelViewMatrix;\n"
1389 "void main(void)\n"
1390 "{\n"
1391 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1392 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1393 "}\n"
1394 "#endif // VERTEX_SHADER\n"
1395 "\n"
1396 "#ifdef FRAGMENT_SHADER\n"
1397 "uniform mat4 ViewToLight;\n"
1398 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1399 "uniform vec2 ScreenToDepth;\n"
1400 "uniform myhalf3 DeferredColor_Ambient;\n"
1401 "uniform myhalf3 DeferredColor_Diffuse;\n"
1402 "#ifdef USESPECULAR\n"
1403 "uniform myhalf3 DeferredColor_Specular;\n"
1404 "uniform myhalf SpecularPower;\n"
1405 "#endif\n"
1406 "uniform myhalf2 PixelToScreenTexCoord;\n"
1407 "void main(void)\n"
1408 "{\n"
1409 "       // calculate viewspace pixel position\n"
1410 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1411 "       vec3 position;\n"
1412 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1413 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1414 "       // decode viewspace pixel normal\n"
1415 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1416 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1417 "       // surfacenormal = pixel normal in viewspace\n"
1418 "       // LightVector = pixel to light in viewspace\n"
1419 "       // CubeVector = position in lightspace\n"
1420 "       // eyevector = pixel to view in viewspace\n"
1421 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1422 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1423 "#ifdef USEDIFFUSE\n"
1424 "       // calculate diffuse shading\n"
1425 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1426 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1427 "#endif\n"
1428 "#ifdef USESPECULAR\n"
1429 "       // calculate directional shading\n"
1430 "       vec3 eyevector = position * -1.0;\n"
1431 "#  ifdef USEEXACTSPECULARMATH\n"
1432 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1433 "#  else\n"
1434 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1435 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1436 "#  endif\n"
1437 "#endif\n"
1438 "\n"
1439 "#if defined(USESHADOWMAP2D)\n"
1440 "       fade *= ShadowMapCompare(CubeVector);\n"
1441 "#endif\n"
1442 "\n"
1443 "#ifdef USEDIFFUSE\n"
1444 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1445 "#else\n"
1446 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1447 "#endif\n"
1448 "#ifdef USESPECULAR\n"
1449 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1450 "#else\n"
1451 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1452 "#endif\n"
1453 "\n"
1454 "# ifdef USECUBEFILTER\n"
1455 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1456 "       gl_FragData[0].rgb *= cubecolor;\n"
1457 "       gl_FragData[1].rgb *= cubecolor;\n"
1458 "# endif\n"
1459 "}\n"
1460 "#endif // FRAGMENT_SHADER\n"
1461 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1462 "\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "#ifdef VERTEX_SHADER\n"
1467 "uniform mat4 TexMatrix;\n"
1468 "#ifdef USEVERTEXTEXTUREBLEND\n"
1469 "uniform mat4 BackgroundTexMatrix;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform mat4 ModelToLight;\n"
1473 "#endif\n"
1474 "#ifdef USESHADOWMAPORTHO\n"
1475 "uniform mat4 ShadowMapMatrix;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1480 "       gl_FrontColor = gl_Color;\n"
1481 "#endif\n"
1482 "       // copy the surface texcoord\n"
1483 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1484 "#ifdef USEVERTEXTEXTUREBLEND\n"
1485 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1486 "#endif\n"
1487 "#ifdef USELIGHTMAP\n"
1488 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1489 "#endif\n"
1490 "\n"
1491 "#ifdef MODE_LIGHTSOURCE\n"
1492 "       // transform vertex position into light attenuation/cubemap space\n"
1493 "       // (-1 to +1 across the light box)\n"
1494 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1495 "\n"
1496 "# ifdef USEDIFFUSE\n"
1497 "       // transform unnormalized light direction into tangent space\n"
1498 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1499 "       //  normalize it per pixel)\n"
1500 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1501 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1502 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1503 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1504 "# endif\n"
1505 "#endif\n"
1506 "\n"
1507 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1508 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1509 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1510 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1511 "#endif\n"
1512 "\n"
1513 "       // transform unnormalized eye direction into tangent space\n"
1514 "#ifdef USEEYEVECTOR\n"
1515 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1516 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1517 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1518 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1519 "#endif\n"
1520 "\n"
1521 "#ifdef USEFOG\n"
1522 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1524 "#endif\n"
1525 "\n"
1526 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1527 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1528 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1529 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1530 "#endif\n"
1531 "\n"
1532 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1533 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1534 "\n"
1535 "#ifdef USESHADOWMAPORTHO\n"
1536 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1537 "#endif\n"
1538 "\n"
1539 "#ifdef USEREFLECTION\n"
1540 "       ModelViewProjectionPosition = gl_Position;\n"
1541 "#endif\n"
1542 "}\n"
1543 "#endif // VERTEX_SHADER\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef FRAGMENT_SHADER\n"
1549 "#ifdef USEDEFERREDLIGHTMAP\n"
1550 "uniform myhalf2 PixelToScreenTexCoord;\n"
1551 "uniform myhalf3 DeferredMod_Diffuse;\n"
1552 "uniform myhalf3 DeferredMod_Specular;\n"
1553 "#endif\n"
1554 "uniform myhalf3 Color_Ambient;\n"
1555 "uniform myhalf3 Color_Diffuse;\n"
1556 "uniform myhalf3 Color_Specular;\n"
1557 "uniform myhalf SpecularPower;\n"
1558 "#ifdef USEGLOW\n"
1559 "uniform myhalf3 Color_Glow;\n"
1560 "#endif\n"
1561 "uniform myhalf Alpha;\n"
1562 "#ifdef USEREFLECTION\n"
1563 "uniform vec4 DistortScaleRefractReflect;\n"
1564 "uniform vec4 ScreenScaleRefractReflect;\n"
1565 "uniform vec4 ScreenCenterRefractReflect;\n"
1566 "uniform myhalf4 ReflectColor;\n"
1567 "#endif\n"
1568 "#ifdef USEREFLECTCUBE\n"
1569 "uniform mat4 ModelToReflectCube;\n"
1570 "uniform sampler2D Texture_ReflectMask;\n"
1571 "uniform samplerCube Texture_ReflectCube;\n"
1572 "#endif\n"
1573 "#ifdef MODE_LIGHTDIRECTION\n"
1574 "uniform myhalf3 LightColor;\n"
1575 "#endif\n"
1576 "#ifdef MODE_LIGHTSOURCE\n"
1577 "uniform myhalf3 LightColor;\n"
1578 "#endif\n"
1579 "void main(void)\n"
1580 "{\n"
1581 "#ifdef USEOFFSETMAPPING\n"
1582 "       // apply offsetmapping\n"
1583 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1584 "#define TexCoord TexCoordOffset\n"
1585 "#endif\n"
1586 "\n"
1587 "       // combine the diffuse textures (base, pants, shirt)\n"
1588 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1589 "#ifdef USEALPHAKILL\n"
1590 "       if (color.a < 0.5)\n"
1591 "               discard;\n"
1592 "#endif\n"
1593 "       color.a *= Alpha;\n"
1594 "#ifdef USECOLORMAPPING\n"
1595 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1596 "#endif\n"
1597 "#ifdef USEVERTEXTEXTUREBLEND\n"
1598 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1599 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1600 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1601 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1602 "       color.a = 1.0;\n"
1603 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1604 "#endif\n"
1605 "\n"
1606 "       // get the surface normal\n"
1607 "#ifdef USEVERTEXTEXTUREBLEND\n"
1608 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1609 "#else\n"
1610 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1611 "#endif\n"
1612 "\n"
1613 "       // get the material colors\n"
1614 "       myhalf3 diffusetex = color.rgb;\n"
1615 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1616 "# ifdef USEVERTEXTEXTUREBLEND\n"
1617 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1618 "# else\n"
1619 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1620 "# endif\n"
1621 "#endif\n"
1622 "\n"
1623 "#ifdef USEREFLECTCUBE\n"
1624 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1625 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1626 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1627 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1628 "#endif\n"
1629 "\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "#ifdef MODE_LIGHTSOURCE\n"
1634 "       // light source\n"
1635 "#ifdef USEDIFFUSE\n"
1636 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1637 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1638 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1639 "#ifdef USESPECULAR\n"
1640 "#ifdef USEEXACTSPECULARMATH\n"
1641 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1642 "#else\n"
1643 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1644 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1645 "#endif\n"
1646 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1647 "#endif\n"
1648 "#else\n"
1649 "       color.rgb = diffusetex * Color_Ambient;\n"
1650 "#endif\n"
1651 "       color.rgb *= LightColor;\n"
1652 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1653 "#if defined(USESHADOWMAP2D)\n"
1654 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1655 "#endif\n"
1656 "# ifdef USECUBEFILTER\n"
1657 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1658 "# endif\n"
1659 "#endif // MODE_LIGHTSOURCE\n"
1660 "\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "#ifdef MODE_LIGHTDIRECTION\n"
1665 "#define SHADING\n"
1666 "#ifdef USEDIFFUSE\n"
1667 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1668 "#endif\n"
1669 "#define lightcolor LightColor\n"
1670 "#endif // MODE_LIGHTDIRECTION\n"
1671 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1672 "#define SHADING\n"
1673 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1674 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1675 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1676 "       // convert modelspace light vector to tangentspace\n"
1677 "       myhalf3 lightnormal;\n"
1678 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1679 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1680 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1681 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1682 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1683 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1684 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1685 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1686 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1687 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1688 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1689 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1690 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1691 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1692 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1693 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1694 "#define SHADING\n"
1695 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1696 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1697 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1698 "#endif\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "#ifdef MODE_FAKELIGHT\n"
1704 "#define SHADING\n"
1705 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1706 "myhalf3 lightcolor = myhalf3(1.0);\n"
1707 "#endif // MODE_FAKELIGHT\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "#ifdef MODE_LIGHTMAP\n"
1713 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1714 "#endif // MODE_LIGHTMAP\n"
1715 "#ifdef MODE_VERTEXCOLOR\n"
1716 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1717 "#endif // MODE_VERTEXCOLOR\n"
1718 "#ifdef MODE_FLATCOLOR\n"
1719 "       color.rgb = diffusetex * Color_Ambient;\n"
1720 "#endif // MODE_FLATCOLOR\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "#ifdef SHADING\n"
1726 "# ifdef USEDIFFUSE\n"
1727 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1728 "#  ifdef USESPECULAR\n"
1729 "#   ifdef USEEXACTSPECULARMATH\n"
1730 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1731 "#   else\n"
1732 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1733 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1734 "#   endif\n"
1735 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1736 "#  else\n"
1737 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1738 "#  endif\n"
1739 "# else\n"
1740 "       color.rgb = diffusetex * Color_Ambient;\n"
1741 "# endif\n"
1742 "#endif\n"
1743 "\n"
1744 "#ifdef USESHADOWMAPORTHO\n"
1745 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef USEDEFERREDLIGHTMAP\n"
1749 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1750 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1751 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1752 "#endif\n"
1753 "\n"
1754 "#ifdef USEGLOW\n"
1755 "#ifdef USEVERTEXTEXTUREBLEND\n"
1756 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1757 "#else\n"
1758 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1759 "#endif\n"
1760 "#endif\n"
1761 "\n"
1762 "#ifdef USEFOG\n"
1763 "       color.rgb = FogVertex(color.rgb);\n"
1764 "#endif\n"
1765 "\n"
1766 "       // 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"
1767 "#ifdef USEREFLECTION\n"
1768 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1769 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1770 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1771 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1772 "       // FIXME temporary hack to detect the case that the reflection\n"
1773 "       // gets blackened at edges due to leaving the area that contains actual\n"
1774 "       // content.\n"
1775 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1776 "       // 'appening.\n"
1777 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1781 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1782 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1783 "#endif\n"
1784 "\n"
1785 "       gl_FragColor = vec4(color);\n"
1786 "}\n"
1787 "#endif // FRAGMENT_SHADER\n"
1788 "\n"
1789 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1790 "#endif // !MODE_DEFERREDGEOMETRY\n"
1791 "#endif // !MODE_WATER\n"
1792 "#endif // !MODE_REFRACTION\n"
1793 "#endif // !MODE_BLOOMBLUR\n"
1794 "#endif // !MODE_GENERIC\n"
1795 "#endif // !MODE_POSTPROCESS\n"
1796 "#endif // !MODE_SHOWDEPTH\n"
1797 "#endif // !MODE_DEPTH_OR_SHADOW\n"
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
1828 const char *builtincgshaderstring =
1829 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1830 "// written by Forest 'LordHavoc' Hale\n"
1831 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1832 "\n"
1833 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1834 "#if defined(USEREFLECTION)\n"
1835 "#undef USESHADOWMAPORTHO\n"
1836 "#endif\n"
1837 "\n"
1838 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1839 "# define USEFOG\n"
1840 "#endif\n"
1841 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1842 "#define USELIGHTMAP\n"
1843 "#endif\n"
1844 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1845 "#define USEEYEVECTOR\n"
1846 "#endif\n"
1847 "\n"
1848 "#ifdef FRAGMENT_SHADER\n"
1849 "#ifdef HLSL\n"
1850 "//#undef USESHADOWMAPPCF\n"
1851 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1852 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1853 "#else\n"
1854 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1855 "#endif\n"
1856 "#endif\n"
1857 "\n"
1858 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float Depth : TEXCOORD0\n"
1866 ")\n"
1867 "{\n"
1868 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1869 "       Depth = gl_Position.z;\n"
1870 "}\n"
1871 "#endif\n"
1872 "\n"
1873 "#ifdef FRAGMENT_SHADER\n"
1874 "void main\n"
1875 "(\n"
1876 "float Depth : TEXCOORD0,\n"
1877 "out float4 gl_FragColor : COLOR\n"
1878 ")\n"
1879 "{\n"
1880 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1881 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1882 "       temp.yz -= floor(temp.yz);\n"
1883 "       gl_FragColor = temp;\n"
1884 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1885 "}\n"
1886 "#endif\n"
1887 "#else // !MODE_DEPTH_ORSHADOW\n"
1888 "\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "#ifdef MODE_SHOWDEPTH\n"
1893 "#ifdef VERTEX_SHADER\n"
1894 "void main\n"
1895 "(\n"
1896 "float4 gl_Vertex : POSITION,\n"
1897 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1898 "out float4 gl_Position : POSITION,\n"
1899 "out float4 gl_FrontColor : COLOR0\n"
1900 ")\n"
1901 "{\n"
1902 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1903 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1904 "}\n"
1905 "#endif\n"
1906 "\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1908 "void main\n"
1909 "(\n"
1910 "float4 gl_FrontColor : COLOR0,\n"
1911 "out float4 gl_FragColor : COLOR\n"
1912 ")\n"
1913 "{\n"
1914 "       gl_FragColor = gl_FrontColor;\n"
1915 "}\n"
1916 "#endif\n"
1917 "#else // !MODE_SHOWDEPTH\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "#ifdef MODE_POSTPROCESS\n"
1923 "\n"
1924 "#ifdef VERTEX_SHADER\n"
1925 "void main\n"
1926 "(\n"
1927 "float4 gl_Vertex : POSITION,\n"
1928 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1929 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1930 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord1 : TEXCOORD0,\n"
1933 "out float2 TexCoord2 : TEXCOORD1\n"
1934 ")\n"
1935 "{\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1938 "#ifdef USEBLOOM\n"
1939 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1940 "#endif\n"
1941 "}\n"
1942 "#endif\n"
1943 "\n"
1944 "#ifdef FRAGMENT_SHADER\n"
1945 "void main\n"
1946 "(\n"
1947 "float2 TexCoord1 : TEXCOORD0,\n"
1948 "float2 TexCoord2 : TEXCOORD1,\n"
1949 "uniform sampler Texture_First : register(s0),\n"
1950 "#ifdef USEBLOOM\n"
1951 "uniform sampler Texture_Second : register(s1),\n"
1952 "#endif\n"
1953 "#ifdef USEGAMMARAMPS\n"
1954 "uniform sampler Texture_GammaRamps : register(s2),\n"
1955 "#endif\n"
1956 "#ifdef USESATURATION\n"
1957 "uniform float Saturation : register(c30),\n"
1958 "#endif\n"
1959 "#ifdef USEVIEWTINT\n"
1960 "uniform float4 ViewTintColor : register(c41),\n"
1961 "#endif\n"
1962 "uniform float4 UserVec1 : register(c37),\n"
1963 "uniform float4 UserVec2 : register(c38),\n"
1964 "uniform float4 UserVec3 : register(c39),\n"
1965 "uniform float4 UserVec4 : register(c40),\n"
1966 "uniform float ClientTime : register(c2),\n"
1967 "uniform float2 PixelSize : register(c25),\n"
1968 "uniform float4 BloomColorSubtract : register(c43),\n"
1969 "out float4 gl_FragColor : COLOR\n"
1970 ")\n"
1971 "{\n"
1972 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1973 "#ifdef USEBLOOM\n"
1974 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1975 "#endif\n"
1976 "#ifdef USEVIEWTINT\n"
1977 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1978 "#endif\n"
1979 "\n"
1980 "#ifdef USEPOSTPROCESSING\n"
1981 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1982 "// 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"
1983 "       float sobel = 1.0;\n"
1984 "       // float2 ts = textureSize(Texture_First, 0);\n"
1985 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1986 "       float2 px = PixelSize;\n"
1987 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1988 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1989 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1992 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1993 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1995 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1996 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1997 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1998 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1999 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2000 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2001 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2002 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2003 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2004 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2005 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2006 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2007 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2008 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2009 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2010 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2011 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2012 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2017 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2018 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2019 "#endif\n"
2020 "\n"
2021 "#ifdef USESATURATION\n"
2022 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2023 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2024 "       // 'vampire sight' effect, wheres red is compensated\n"
2025 "       #ifdef SATURATION_REDCOMPENSATE\n"
2026 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2027 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2028 "               gl_FragColor.r += r;\n"
2029 "       #else\n"
2030 "               // normal desaturation\n"
2031 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2032 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2033 "       #endif\n"
2034 "#endif\n"
2035 "\n"
2036 "#ifdef USEGAMMARAMPS\n"
2037 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2038 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2039 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2040 "#endif\n"
2041 "}\n"
2042 "#endif\n"
2043 "#else // !MODE_POSTPROCESS\n"
2044 "\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "#ifdef MODE_GENERIC\n"
2049 "#ifdef VERTEX_SHADER\n"
2050 "void main\n"
2051 "(\n"
2052 "float4 gl_Vertex : POSITION,\n"
2053 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2054 "float4 gl_Color : COLOR0,\n"
2055 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2056 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2057 "out float4 gl_Position : POSITION,\n"
2058 "#ifdef USEDIFFUSE\n"
2059 "out float2 TexCoord1 : TEXCOORD0,\n"
2060 "#endif\n"
2061 "#ifdef USESPECULAR\n"
2062 "out float2 TexCoord2 : TEXCOORD1,\n"
2063 "#endif\n"
2064 "out float4 gl_FrontColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "#ifdef HLSL\n"
2068 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2069 "#else\n"
2070 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2071 "#endif\n"
2072 "#ifdef USEDIFFUSE\n"
2073 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2074 "#endif\n"
2075 "#ifdef USESPECULAR\n"
2076 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2077 "#endif\n"
2078 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2079 "}\n"
2080 "#endif\n"
2081 "\n"
2082 "#ifdef FRAGMENT_SHADER\n"
2083 "\n"
2084 "void main\n"
2085 "(\n"
2086 "float4 gl_FrontColor : COLOR0,\n"
2087 "float2 TexCoord1 : TEXCOORD0,\n"
2088 "float2 TexCoord2 : TEXCOORD1,\n"
2089 "#ifdef USEDIFFUSE\n"
2090 "uniform sampler Texture_First : register(s0),\n"
2091 "#endif\n"
2092 "#ifdef USESPECULAR\n"
2093 "uniform sampler Texture_Second : register(s1),\n"
2094 "#endif\n"
2095 "out float4 gl_FragColor : COLOR\n"
2096 ")\n"
2097 "{\n"
2098 "#ifdef USEVIEWTINT\n"
2099 "       gl_FragColor = gl_FrontColor;\n"
2100 "#else\n"
2101 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2102 "#endif\n"
2103 "#ifdef USEDIFFUSE\n"
2104 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2105 "#endif\n"
2106 "\n"
2107 "#ifdef USESPECULAR\n"
2108 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2109 "# ifdef USECOLORMAPPING\n"
2110 "       gl_FragColor *= tex2;\n"
2111 "# endif\n"
2112 "# ifdef USEGLOW\n"
2113 "       gl_FragColor += tex2;\n"
2114 "# endif\n"
2115 "# ifdef USEVERTEXTEXTUREBLEND\n"
2116 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2117 "# endif\n"
2118 "#endif\n"
2119 "}\n"
2120 "#endif\n"
2121 "#else // !MODE_GENERIC\n"
2122 "\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "#ifdef MODE_BLOOMBLUR\n"
2127 "#ifdef VERTEX_SHADER\n"
2128 "void main\n"
2129 "(\n"
2130 "float4 gl_Vertex : POSITION,\n"
2131 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2132 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2133 "out float4 gl_Position : POSITION,\n"
2134 "out float2 TexCoord : TEXCOORD0\n"
2135 ")\n"
2136 "{\n"
2137 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2138 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2139 "}\n"
2140 "#endif\n"
2141 "\n"
2142 "#ifdef FRAGMENT_SHADER\n"
2143 "\n"
2144 "void main\n"
2145 "(\n"
2146 "float2 TexCoord : TEXCOORD0,\n"
2147 "uniform sampler Texture_First : register(s0),\n"
2148 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2149 "out float4 gl_FragColor : COLOR\n"
2150 ")\n"
2151 "{\n"
2152 "       int i;\n"
2153 "       float2 tc = TexCoord;\n"
2154 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2155 "       tc += BloomBlur_Parameters.xy;\n"
2156 "       for (i = 1;i < SAMPLES;i++)\n"
2157 "       {\n"
2158 "               color += tex2D(Texture_First, tc).rgb;\n"
2159 "               tc += BloomBlur_Parameters.xy;\n"
2160 "       }\n"
2161 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2162 "}\n"
2163 "#endif\n"
2164 "#else // !MODE_BLOOMBLUR\n"
2165 "#ifdef MODE_REFRACTION\n"
2166 "#ifdef VERTEX_SHADER\n"
2167 "void main\n"
2168 "(\n"
2169 "float4 gl_Vertex : POSITION,\n"
2170 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2171 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2172 "uniform float4x4 TexMatrix : register(c0),\n"
2173 "uniform float3 EyePosition : register(c24),\n"
2174 "out float4 gl_Position : POSITION,\n"
2175 "out float2 TexCoord : TEXCOORD0,\n"
2176 "out float3 EyeVector : TEXCOORD1,\n"
2177 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2178 ")\n"
2179 "{\n"
2180 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2181 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2182 "       ModelViewProjectionPosition = gl_Position;\n"
2183 "}\n"
2184 "#endif\n"
2185 "\n"
2186 "#ifdef FRAGMENT_SHADER\n"
2187 "void main\n"
2188 "(\n"
2189 "float2 TexCoord : TEXCOORD0,\n"
2190 "float3 EyeVector : TEXCOORD1,\n"
2191 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2192 "uniform sampler Texture_Normal : register(s0),\n"
2193 "uniform sampler Texture_Refraction : register(s3),\n"
2194 "uniform sampler Texture_Reflection : register(s7),\n"
2195 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2196 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2197 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2198 "uniform float4 RefractColor : register(c29),\n"
2199 "out float4 gl_FragColor : COLOR\n"
2200 ")\n"
2201 "{\n"
2202 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2203 "       //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"
2204 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2206 "       // FIXME temporary hack to detect the case that the reflection\n"
2207 "       // gets blackened at edges due to leaving the area that contains actual\n"
2208 "       // content.\n"
2209 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2210 "       // 'appening.\n"
2211 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2215 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2216 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2217 "}\n"
2218 "#endif\n"
2219 "#else // !MODE_REFRACTION\n"
2220 "\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "#ifdef MODE_WATER\n"
2225 "#ifdef VERTEX_SHADER\n"
2226 "\n"
2227 "void main\n"
2228 "(\n"
2229 "float4 gl_Vertex : POSITION,\n"
2230 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2231 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2232 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2233 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2234 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2235 "uniform float4x4 TexMatrix : register(c0),\n"
2236 "uniform float3 EyePosition : register(c24),\n"
2237 "out float4 gl_Position : POSITION,\n"
2238 "out float2 TexCoord : TEXCOORD0,\n"
2239 "out float3 EyeVector : TEXCOORD1,\n"
2240 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2241 ")\n"
2242 "{\n"
2243 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2244 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2245 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2246 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2247 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2248 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2249 "       ModelViewProjectionPosition = gl_Position;\n"
2250 "}\n"
2251 "#endif\n"
2252 "\n"
2253 "#ifdef FRAGMENT_SHADER\n"
2254 "void main\n"
2255 "(\n"
2256 "float2 TexCoord : TEXCOORD0,\n"
2257 "float3 EyeVector : TEXCOORD1,\n"
2258 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2259 "uniform sampler Texture_Normal : register(s0),\n"
2260 "uniform sampler Texture_Refraction : register(s3),\n"
2261 "uniform sampler Texture_Reflection : register(s7),\n"
2262 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2263 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2264 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2265 "uniform float4 RefractColor : register(c29),\n"
2266 "uniform float4 ReflectColor : register(c26),\n"
2267 "uniform float ReflectFactor : register(c27),\n"
2268 "uniform float ReflectOffset : register(c28),\n"
2269 "out float4 gl_FragColor : COLOR\n"
2270 ")\n"
2271 "{\n"
2272 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2273 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2274 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2276 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2277 "       // FIXME temporary hack to detect the case that the reflection\n"
2278 "       // gets blackened at edges due to leaving the area that contains actual\n"
2279 "       // content.\n"
2280 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2281 "       // 'appening.\n"
2282 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2286 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2291 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2292 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2293 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2294 "}\n"
2295 "#endif\n"
2296 "#else // !MODE_WATER\n"
2297 "\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "// 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"
2302 "\n"
2303 "// fragment shader specific:\n"
2304 "#ifdef FRAGMENT_SHADER\n"
2305 "\n"
2306 "#ifdef USEFOG\n"
2307 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2308 "{\n"
2309 "       float fogfrac;\n"
2310 "#ifdef USEFOGHEIGHTTEXTURE\n"
2311 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2312 "       fogfrac = fogheightpixel.a;\n"
2313 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2314 "#else\n"
2315 "# ifdef USEFOGOUTSIDE\n"
2316 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2317 "# else\n"
2318 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2319 "# endif\n"
2320 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2321 "#endif\n"
2322 "}\n"
2323 "#endif\n"
2324 "\n"
2325 "#ifdef USEOFFSETMAPPING\n"
2326 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2327 "{\n"
2328 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2329 "       // 14 sample relief mapping: linear search and then binary search\n"
2330 "       // this basically steps forward a small amount repeatedly until it finds\n"
2331 "       // itself inside solid, then jitters forward and back using decreasing\n"
2332 "       // amounts to find the impact\n"
2333 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2334 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2335 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 RT = float3(TexCoord, 1);\n"
2337 "       OffsetVector *= 0.1;\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);\n"
2347 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2352 "       return RT.xy;\n"
2353 "#else\n"
2354 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2355 "       // this basically moves forward the full distance, and then backs up based\n"
2356 "       // on height of samples\n"
2357 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2358 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2359 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       TexCoord += OffsetVector;\n"
2361 "       OffsetVector *= 0.333;\n"
2362 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       return TexCoord;\n"
2366 "#endif\n"
2367 "}\n"
2368 "#endif // USEOFFSETMAPPING\n"
2369 "\n"
2370 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2371 "#if defined(USESHADOWMAP2D)\n"
2372 "# ifdef USESHADOWMAPORTHO\n"
2373 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2374 "# else\n"
2375 "#  ifdef USESHADOWMAPVSDCT\n"
2376 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2377 "{\n"
2378 "       float3 adir = abs(dir);\n"
2379 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2380 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2381 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2382 "}\n"
2383 "#  else\n"
2384 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2385 "{\n"
2386 "       float3 adir = abs(dir);\n"
2387 "       float ma = adir.z;\n"
2388 "       float4 proj = float4(dir, 2.5);\n"
2389 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2390 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2391 "#ifdef HLSL\n"
2392 "       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"
2393 "#else\n"
2394 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2395 "       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"
2396 "#endif\n"
2397 "}\n"
2398 "#  endif\n"
2399 "# endif\n"
2400 "#endif // defined(USESHADOWMAP2D)\n"
2401 "\n"
2402 "# ifdef USESHADOWMAP2D\n"
2403 "#ifdef USESHADOWMAPVSDCT\n"
2404 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2405 "#else\n"
2406 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2407 "#endif\n"
2408 "{\n"
2409 "#ifdef USESHADOWMAPVSDCT\n"
2410 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2411 "#else\n"
2412 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2413 "#endif\n"
2414 "       float f;\n"
2415 "\n"
2416 "#  ifdef USESHADOWSAMPLER\n"
2417 "#    ifdef USESHADOWMAPPCF\n"
2418 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2419 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2420 "       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"
2421 "#    else\n"
2422 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2423 "#    endif\n"
2424 "#  else\n"
2425 "#    ifdef USESHADOWMAPPCF\n"
2426 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2427 "#      ifdef GL_ARB_texture_gather\n"
2428 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2429 "#      else\n"
2430 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2431 "#      endif\n"
2432 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2433 "#      if USESHADOWMAPPCF > 1\n"
2434 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2435 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2436 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2437 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2438 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2439 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2440 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2441 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2442 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2443 "       float4 locols = float4(group1.ab, group3.ab);\n"
2444 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2445 "       locols.yz += group2.ab;\n"
2446 "       hicols.yz += group8.rg;\n"
2447 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2448 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2449 "                               lerp(locols, hicols, offset.y);\n"
2450 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2451 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2452 "       f = dot(cols, float4(1.0/25.0));\n"
2453 "#      else\n"
2454 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2455 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2456 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2457 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2458 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2459 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2460 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2461 "#      endif\n"
2462 "#     else\n"
2463 "#      ifdef GL_EXT_gpu_shader4\n"
2464 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2465 "#      else\n"
2466 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2467 "#      endif\n"
2468 "#      if USESHADOWMAPPCF > 1\n"
2469 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2470 "       center *= ShadowMap_TextureScale;\n"
2471 "       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"
2472 "       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"
2473 "       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"
2474 "       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"
2475 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2476 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2477 "#      else\n"
2478 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2479 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2480 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2481 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2482 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2483 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2484 "#      endif\n"
2485 "#     endif\n"
2486 "#    else\n"
2487 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2488 "#    endif\n"
2489 "#  endif\n"
2490 "#  ifdef USESHADOWMAPORTHO\n"
2491 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2492 "#  else\n"
2493 "       return f;\n"
2494 "#  endif\n"
2495 "}\n"
2496 "# endif\n"
2497 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2498 "#endif // FRAGMENT_SHADER\n"
2499 "\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "#ifdef MODE_DEFERREDGEOMETRY\n"
2504 "#ifdef VERTEX_SHADER\n"
2505 "void main\n"
2506 "(\n"
2507 "float4 gl_Vertex : POSITION,\n"
2508 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2509 "#ifdef USEVERTEXTEXTUREBLEND\n"
2510 "float4 gl_Color : COLOR0,\n"
2511 "#endif\n"
2512 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2513 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2514 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2515 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2516 "uniform float4x4 TexMatrix : register(c0),\n"
2517 "#ifdef USEVERTEXTEXTUREBLEND\n"
2518 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2519 "#endif\n"
2520 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2521 "#ifdef USEOFFSETMAPPING\n"
2522 "uniform float3 EyePosition : register(c24),\n"
2523 "#endif\n"
2524 "out float4 gl_Position : POSITION,\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "out float4 gl_FrontColor : COLOR,\n"
2527 "#endif\n"
2528 "out float4 TexCoordBoth : TEXCOORD0,\n"
2529 "#ifdef USEOFFSETMAPPING\n"
2530 "out float3 EyeVector : TEXCOORD2,\n"
2531 "#endif\n"
2532 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2533 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2534 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2535 ")\n"
2536 "{\n"
2537 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2538 "#ifdef USEVERTEXTEXTUREBLEND\n"
2539 "#ifdef HLSL\n"
2540 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2541 "#else\n"
2542 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2543 "#endif\n"
2544 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2545 "#endif\n"
2546 "\n"
2547 "       // transform unnormalized eye direction into tangent space\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2550 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2551 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2552 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2553 "#endif\n"
2554 "\n"
2555 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2556 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2557 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2558 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2559 "       VectorR.w = gl_Position.z;\n"
2560 "}\n"
2561 "#endif // VERTEX_SHADER\n"
2562 "\n"
2563 "#ifdef FRAGMENT_SHADER\n"
2564 "void main\n"
2565 "(\n"
2566 "float4 TexCoordBoth : TEXCOORD0,\n"
2567 "float3 EyeVector : TEXCOORD2,\n"
2568 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2569 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2570 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2571 "uniform sampler Texture_Normal : register(s0),\n"
2572 "#ifdef USEALPHAKILL\n"
2573 "uniform sampler Texture_Color : register(s1),\n"
2574 "#endif\n"
2575 "uniform sampler Texture_Gloss : register(s2),\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2578 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2579 "#endif\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 "uniform float OffsetMapping_Scale : register(c24),\n"
2582 "#endif\n"
2583 "uniform half SpecularPower : register(c36),\n"
2584 "#ifdef HLSL\n"
2585 "out float4 gl_FragData0 : COLOR0,\n"
2586 "out float4 gl_FragData1 : COLOR1\n"
2587 "#else\n"
2588 "out float4 gl_FragColor : COLOR\n"
2589 "#endif\n"
2590 ")\n"
2591 "{\n"
2592 "       float2 TexCoord = TexCoordBoth.xy;\n"
2593 "#ifdef USEOFFSETMAPPING\n"
2594 "       // apply offsetmapping\n"
2595 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2596 "#define TexCoord TexCoordOffset\n"
2597 "#endif\n"
2598 "\n"
2599 "#ifdef USEALPHAKILL\n"
2600 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2601 "               discard;\n"
2602 "#endif\n"
2603 "\n"
2604 "#ifdef USEVERTEXTEXTUREBLEND\n"
2605 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2606 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2607 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2608 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2609 "#endif\n"
2610 "\n"
2611 "#ifdef USEVERTEXTEXTUREBLEND\n"
2612 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2613 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2614 "#else\n"
2615 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2616 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2617 "#endif\n"
2618 "\n"
2619 "#ifdef HLSL\n"
2620 "       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"
2621 "       float Depth = VectorR.w / 256.0;\n"
2622 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2623 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2624 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2625 "       gl_FragData1 = depthcolor;\n"
2626 "#else\n"
2627 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2628 "#endif\n"
2629 "}\n"
2630 "#endif // FRAGMENT_SHADER\n"
2631 "#else // !MODE_DEFERREDGEOMETRY\n"
2632 "\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2637 "#ifdef VERTEX_SHADER\n"
2638 "void main\n"
2639 "(\n"
2640 "float4 gl_Vertex : POSITION,\n"
2641 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2642 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2643 "out float4 gl_Position : POSITION,\n"
2644 "out float4 ModelViewPosition : TEXCOORD0\n"
2645 ")\n"
2646 "{\n"
2647 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2648 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2649 "}\n"
2650 "#endif // VERTEX_SHADER\n"
2651 "\n"
2652 "#ifdef FRAGMENT_SHADER\n"
2653 "void main\n"
2654 "(\n"
2655 "#ifdef HLSL\n"
2656 "float2 Pixel : VPOS,\n"
2657 "#else\n"
2658 "float2 Pixel : WPOS,\n"
2659 "#endif\n"
2660 "float4 ModelViewPosition : TEXCOORD0,\n"
2661 "uniform float4x4 ViewToLight : register(c44),\n"
2662 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2663 "uniform float3 LightPosition : register(c23),\n"
2664 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2665 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2666 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2667 "#ifdef USESPECULAR\n"
2668 "uniform half3 DeferredColor_Specular : register(c11),\n"
2669 "uniform half SpecularPower : register(c36),\n"
2670 "#endif\n"
2671 "uniform sampler Texture_Attenuation : register(s9),\n"
2672 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2673 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2674 "\n"
2675 "#ifdef USECUBEFILTER\n"
2676 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2677 "#endif\n"
2678 "\n"
2679 "#ifdef USESHADOWMAP2D\n"
2680 "# ifdef USESHADOWSAMPLER\n"
2681 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2682 "# else\n"
2683 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2684 "# endif\n"
2685 "#endif\n"
2686 "\n"
2687 "#ifdef USESHADOWMAPVSDCT\n"
2688 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2689 "#endif\n"
2690 "\n"
2691 "#if defined(USESHADOWMAP2D)\n"
2692 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2693 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2694 "#endif\n"
2695 "\n"
2696 "out float4 gl_FragData0 : COLOR0,\n"
2697 "out float4 gl_FragData1 : COLOR1\n"
2698 ")\n"
2699 "{\n"
2700 "       // calculate viewspace pixel position\n"
2701 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2702 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2703 "       float3 position;\n"
2704 "#ifdef HLSL\n"
2705 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2706 "#else\n"
2707 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2708 "#endif\n"
2709 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2710 "       // decode viewspace pixel normal\n"
2711 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2712 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2713 "       // surfacenormal = pixel normal in viewspace\n"
2714 "       // LightVector = pixel to light in viewspace\n"
2715 "       // CubeVector = position in lightspace\n"
2716 "       // eyevector = pixel to view in viewspace\n"
2717 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2718 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2719 "#ifdef USEDIFFUSE\n"
2720 "       // calculate diffuse shading\n"
2721 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2722 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2723 "#endif\n"
2724 "#ifdef USESPECULAR\n"
2725 "       // calculate directional shading\n"
2726 "       float3 eyevector = position * -1.0;\n"
2727 "#  ifdef USEEXACTSPECULARMATH\n"
2728 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2729 "#  else\n"
2730 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2731 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2732 "#  endif\n"
2733 "#endif\n"
2734 "\n"
2735 "#if defined(USESHADOWMAP2D)\n"
2736 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2737 "#ifdef USESHADOWMAPVSDCT\n"
2738 ", Texture_CubeProjection\n"
2739 "#endif\n"
2740 "       ));\n"
2741 "#endif\n"
2742 "\n"
2743 "#ifdef USEDIFFUSE\n"
2744 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2745 "#else\n"
2746 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2747 "#endif\n"
2748 "#ifdef USESPECULAR\n"
2749 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2750 "#else\n"
2751 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2752 "#endif\n"
2753 "\n"
2754 "# ifdef USECUBEFILTER\n"
2755 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2756 "       gl_FragData0.rgb *= cubecolor;\n"
2757 "       gl_FragData1.rgb *= cubecolor;\n"
2758 "# endif\n"
2759 "}\n"
2760 "#endif // FRAGMENT_SHADER\n"
2761 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2762 "\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "#ifdef VERTEX_SHADER\n"
2767 "void main\n"
2768 "(\n"
2769 "float4 gl_Vertex : POSITION,\n"
2770 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2771 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2772 "float4 gl_Color : COLOR0,\n"
2773 "#endif\n"
2774 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2775 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2776 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2777 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2778 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2779 "\n"
2780 "uniform float3 EyePosition : register(c24),\n"
2781 "uniform float4x4 TexMatrix : register(c0),\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2784 "#endif\n"
2785 "#ifdef MODE_LIGHTSOURCE\n"
2786 "uniform float4x4 ModelToLight : register(c20),\n"
2787 "#endif\n"
2788 "#ifdef MODE_LIGHTSOURCE\n"
2789 "uniform float3 LightPosition : register(c27),\n"
2790 "#endif\n"
2791 "#ifdef MODE_LIGHTDIRECTION\n"
2792 "uniform float3 LightDir : register(c26),\n"
2793 "#endif\n"
2794 "uniform float4 FogPlane : register(c25),\n"
2795 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2796 "uniform float3 LightPosition : register(c27),\n"
2797 "#endif\n"
2798 "#ifdef USESHADOWMAPORTHO\n"
2799 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2800 "#endif\n"
2801 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2802 "out float4 gl_FrontColor : COLOR,\n"
2803 "#endif\n"
2804 "out float4 TexCoordBoth : TEXCOORD0,\n"
2805 "#ifdef USELIGHTMAP\n"
2806 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2807 "#endif\n"
2808 "#ifdef USEEYEVECTOR\n"
2809 "out float3 EyeVector : TEXCOORD2,\n"
2810 "#endif\n"
2811 "#ifdef USEREFLECTION\n"
2812 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2813 "#endif\n"
2814 "#ifdef USEFOG\n"
2815 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2816 "#endif\n"
2817 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2818 "out float3 LightVector : TEXCOORD1,\n"
2819 "#endif\n"
2820 "#ifdef MODE_LIGHTSOURCE\n"
2821 "out float3 CubeVector : TEXCOORD3,\n"
2822 "#endif\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2824 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2825 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2826 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2827 "#endif\n"
2828 "#ifdef USESHADOWMAPORTHO\n"
2829 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2830 "#endif\n"
2831 "out float4 gl_Position : POSITION\n"
2832 ")\n"
2833 "{\n"
2834 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2835 "#ifdef HLSL\n"
2836 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2837 "#else\n"
2838 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2839 "#endif\n"
2840 "#endif\n"
2841 "       // copy the surface texcoord\n"
2842 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2845 "#endif\n"
2846 "#ifdef USELIGHTMAP\n"
2847 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "       // transform vertex position into light attenuation/cubemap space\n"
2852 "       // (-1 to +1 across the light box)\n"
2853 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2854 "\n"
2855 "# ifdef USEDIFFUSE\n"
2856 "       // transform unnormalized light direction into tangent space\n"
2857 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2858 "       //  normalize it per pixel)\n"
2859 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2860 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2861 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2862 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2867 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2868 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2869 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2870 "#endif\n"
2871 "\n"
2872 "       // transform unnormalized eye direction into tangent space\n"
2873 "#ifdef USEEYEVECTOR\n"
2874 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2878 "#endif\n"
2879 "\n"
2880 "#ifdef USEFOG\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2883 "#endif\n"
2884 "\n"
2885 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2886 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2887 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2888 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2892 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2893 "\n"
2894 "#ifdef USESHADOWMAPORTHO\n"
2895 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USEREFLECTION\n"
2899 "       ModelViewProjectionPosition = gl_Position;\n"
2900 "#endif\n"
2901 "}\n"
2902 "#endif // VERTEX_SHADER\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "#ifdef FRAGMENT_SHADER\n"
2908 "void main\n"
2909 "(\n"
2910 "#ifdef USEDEFERREDLIGHTMAP\n"
2911 "#ifdef HLSL\n"
2912 "float2 Pixel : VPOS,\n"
2913 "#else\n"
2914 "float2 Pixel : WPOS,\n"
2915 "#endif\n"
2916 "#endif\n"
2917 "float4 gl_FrontColor : COLOR,\n"
2918 "float4 TexCoordBoth : TEXCOORD0,\n"
2919 "#ifdef USELIGHTMAP\n"
2920 "float2 TexCoordLightmap : TEXCOORD1,\n"
2921 "#endif\n"
2922 "#ifdef USEEYEVECTOR\n"
2923 "float3 EyeVector : TEXCOORD2,\n"
2924 "#endif\n"
2925 "#ifdef USEREFLECTION\n"
2926 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2927 "#endif\n"
2928 "#ifdef USEFOG\n"
2929 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2930 "#endif\n"
2931 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2932 "float3 LightVector : TEXCOORD1,\n"
2933 "#endif\n"
2934 "#ifdef MODE_LIGHTSOURCE\n"
2935 "float3 CubeVector : TEXCOORD3,\n"
2936 "#endif\n"
2937 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2938 "float4 ModelViewPosition : TEXCOORD0,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "\n"
2949 "uniform sampler Texture_Normal : register(s0),\n"
2950 "uniform sampler Texture_Color : register(s1),\n"
2951 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2952 "uniform sampler Texture_Gloss : register(s2),\n"
2953 "#endif\n"
2954 "#ifdef USEGLOW\n"
2955 "uniform sampler Texture_Glow : register(s3),\n"
2956 "#endif\n"
2957 "#ifdef USEVERTEXTEXTUREBLEND\n"
2958 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2959 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2960 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2961 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2962 "#endif\n"
2963 "#ifdef USEGLOW\n"
2964 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2965 "#endif\n"
2966 "#endif\n"
2967 "#ifdef USECOLORMAPPING\n"
2968 "uniform sampler Texture_Pants : register(s4),\n"
2969 "uniform sampler Texture_Shirt : register(s7),\n"
2970 "#endif\n"
2971 "#ifdef USEFOG\n"
2972 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2973 "uniform sampler Texture_FogMask : register(s8),\n"
2974 "#endif\n"
2975 "#ifdef USELIGHTMAP\n"
2976 "uniform sampler Texture_Lightmap : register(s9),\n"
2977 "#endif\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2979 "uniform sampler Texture_Deluxemap : register(s10),\n"
2980 "#endif\n"
2981 "#ifdef USEREFLECTION\n"
2982 "uniform sampler Texture_Reflection : register(s7),\n"
2983 "#endif\n"
2984 "\n"
2985 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2986 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2987 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2988 "#endif\n"
2989 "#ifdef USEDEFERREDLIGHTMAP\n"
2990 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2991 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2992 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2993 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2994 "#endif\n"
2995 "\n"
2996 "#ifdef USECOLORMAPPING\n"
2997 "uniform half3 Color_Pants : register(c7),\n"
2998 "uniform half3 Color_Shirt : register(c8),\n"
2999 "#endif\n"
3000 "#ifdef USEFOG\n"
3001 "uniform float3 FogColor : register(c16),\n"
3002 "uniform float FogRangeRecip : register(c20),\n"
3003 "uniform float FogPlaneViewDist : register(c19),\n"
3004 "uniform float FogHeightFade : register(c17),\n"
3005 "#endif\n"
3006 "\n"
3007 "#ifdef USEOFFSETMAPPING\n"
3008 "uniform float OffsetMapping_Scale : register(c24),\n"
3009 "#endif\n"
3010 "\n"
3011 "#ifdef USEDEFERREDLIGHTMAP\n"
3012 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3013 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3014 "uniform half3 DeferredMod_Specular : register(c13),\n"
3015 "#endif\n"
3016 "uniform half3 Color_Ambient : register(c3),\n"
3017 "uniform half3 Color_Diffuse : register(c4),\n"
3018 "uniform half3 Color_Specular : register(c5),\n"
3019 "uniform half SpecularPower : register(c36),\n"
3020 "#ifdef USEGLOW\n"
3021 "uniform half3 Color_Glow : register(c6),\n"
3022 "#endif\n"
3023 "uniform half Alpha : register(c0),\n"
3024 "#ifdef USEREFLECTION\n"
3025 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3026 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3027 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3028 "uniform half4 ReflectColor : register(c26),\n"
3029 "#endif\n"
3030 "#ifdef USEREFLECTCUBE\n"
3031 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3032 "uniform sampler Texture_ReflectMask : register(s5),\n"
3033 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3034 "#endif\n"
3035 "#ifdef MODE_LIGHTDIRECTION\n"
3036 "uniform half3 LightColor : register(c21),\n"
3037 "#endif\n"
3038 "#ifdef MODE_LIGHTSOURCE\n"
3039 "uniform half3 LightColor : register(c21),\n"
3040 "#endif\n"
3041 "\n"
3042 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3043 "uniform sampler Texture_Attenuation : register(s9),\n"
3044 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3045 "#endif\n"
3046 "\n"
3047 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3048 "\n"
3049 "#ifdef USESHADOWMAP2D\n"
3050 "# ifdef USESHADOWSAMPLER\n"
3051 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3052 "# else\n"
3053 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3054 "# endif\n"
3055 "#endif\n"
3056 "\n"
3057 "#ifdef USESHADOWMAPVSDCT\n"
3058 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3059 "#endif\n"
3060 "\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3063 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3064 "#endif\n"
3065 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3066 "\n"
3067 "out float4 gl_FragColor : COLOR\n"
3068 ")\n"
3069 "{\n"
3070 "       float2 TexCoord = TexCoordBoth.xy;\n"
3071 "#ifdef USEVERTEXTEXTUREBLEND\n"
3072 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3073 "#endif\n"
3074 "#ifdef USEOFFSETMAPPING\n"
3075 "       // apply offsetmapping\n"
3076 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3077 "#define TexCoord TexCoordOffset\n"
3078 "#endif\n"
3079 "\n"
3080 "       // combine the diffuse textures (base, pants, shirt)\n"
3081 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3082 "#ifdef USEALPHAKILL\n"
3083 "       if (color.a < 0.5)\n"
3084 "               discard;\n"
3085 "#endif\n"
3086 "       color.a *= Alpha;\n"
3087 "#ifdef USECOLORMAPPING\n"
3088 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3089 "#endif\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3092 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3093 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3094 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3095 "       color.a = 1.0;\n"
3096 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3097 "#endif\n"
3098 "\n"
3099 "       // get the surface normal\n"
3100 "#ifdef USEVERTEXTEXTUREBLEND\n"
3101 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3102 "#else\n"
3103 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3104 "#endif\n"
3105 "\n"
3106 "       // get the material colors\n"
3107 "       half3 diffusetex = color.rgb;\n"
3108 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3109 "# ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3111 "# else\n"
3112 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3113 "# endif\n"
3114 "#endif\n"
3115 "\n"
3116 "#ifdef USEREFLECTCUBE\n"
3117 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3118 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3119 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3120 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3121 "#endif\n"
3122 "\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "#ifdef MODE_LIGHTSOURCE\n"
3127 "       // light source\n"
3128 "#ifdef USEDIFFUSE\n"
3129 "       half3 lightnormal = half3(normalize(LightVector));\n"
3130 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3131 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3132 "#ifdef USESPECULAR\n"
3133 "#ifdef USEEXACTSPECULARMATH\n"
3134 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3135 "#else\n"
3136 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3137 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3138 "#endif\n"
3139 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3140 "#endif\n"
3141 "#else\n"
3142 "       color.rgb = diffusetex * Color_Ambient;\n"
3143 "#endif\n"
3144 "       color.rgb *= LightColor;\n"
3145 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3146 "#if defined(USESHADOWMAP2D)\n"
3147 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3148 "#ifdef USESHADOWMAPVSDCT\n"
3149 ", Texture_CubeProjection\n"
3150 "#endif\n"
3151 "       ));\n"
3152 "\n"
3153 "#endif\n"
3154 "# ifdef USECUBEFILTER\n"
3155 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3156 "# endif\n"
3157 "\n"
3158 "#ifdef USESHADOWMAP2D\n"
3159 "#ifdef USESHADOWMAPVSDCT\n"
3160 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3161 "#else\n"
3162 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3163 "#endif\n"
3164 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3166 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3167 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3168 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3170 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3171 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3172 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z);\n"
3174 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3175 "//     color.r = half(shadowmaptc.z);\n"
3176 "//     color.r = 1;\n"
3177 "//     color.rgb = abs(CubeVector);\n"
3178 "#endif\n"
3179 "//     color.rgb = half3(1,1,1);\n"
3180 "#endif // MODE_LIGHTSOURCE\n"
3181 "\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "#ifdef MODE_LIGHTDIRECTION\n"
3186 "#define SHADING\n"
3187 "#ifdef USEDIFFUSE\n"
3188 "       half3 lightnormal = half3(normalize(LightVector));\n"
3189 "#endif\n"
3190 "#define lightcolor LightColor\n"
3191 "#endif // MODE_LIGHTDIRECTION\n"
3192 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3193 "#define SHADING\n"
3194 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3195 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3196 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3197 "       // convert modelspace light vector to tangentspace\n"
3198 "       half3 lightnormal;\n"
3199 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3200 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3201 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3202 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3203 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3204 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3205 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3206 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3207 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3208 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3209 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3210 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3211 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3212 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3213 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3214 "#define SHADING\n"
3215 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3216 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3217 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3218 "#endif\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "#ifdef MODE_FAKELIGHT\n"
3224 "#define SHADING\n"
3225 "half3 lightnormal = half3(normalize(EyeVector));\n"
3226 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3227 "#endif // MODE_FAKELIGHT\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "#ifdef MODE_LIGHTMAP\n"
3233 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3234 "#endif // MODE_LIGHTMAP\n"
3235 "#ifdef MODE_VERTEXCOLOR\n"
3236 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3237 "#endif // MODE_VERTEXCOLOR\n"
3238 "#ifdef MODE_FLATCOLOR\n"
3239 "       color.rgb = diffusetex * Color_Ambient;\n"
3240 "#endif // MODE_FLATCOLOR\n"
3241 "\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "#ifdef SHADING\n"
3246 "# ifdef USEDIFFUSE\n"
3247 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3248 "#  ifdef USESPECULAR\n"
3249 "#   ifdef USEEXACTSPECULARMATH\n"
3250 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3251 "#   else\n"
3252 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3253 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3254 "#   endif\n"
3255 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3256 "#  else\n"
3257 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3258 "#  endif\n"
3259 "# else\n"
3260 "       color.rgb = diffusetex * Color_Ambient;\n"
3261 "# endif\n"
3262 "#endif\n"
3263 "\n"
3264 "#ifdef USESHADOWMAPORTHO\n"
3265 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3266 "#endif\n"
3267 "\n"
3268 "#ifdef USEDEFERREDLIGHTMAP\n"
3269 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3270 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3271 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3272 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3273 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3274 "#endif\n"
3275 "\n"
3276 "#ifdef USEGLOW\n"
3277 "#ifdef USEVERTEXTEXTUREBLEND\n"
3278 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3279 "#else\n"
3280 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3281 "#endif\n"
3282 "#endif\n"
3283 "\n"
3284 "#ifdef USEFOG\n"
3285 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3286 "#endif\n"
3287 "\n"
3288 "       // 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"
3289 "#ifdef USEREFLECTION\n"
3290 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3291 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3292 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3293 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3294 "       // FIXME temporary hack to detect the case that the reflection\n"
3295 "       // gets blackened at edges due to leaving the area that contains actual\n"
3296 "       // content.\n"
3297 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3298 "       // 'appening.\n"
3299 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3303 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3304 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3305 "#endif\n"
3306 "\n"
3307 "       gl_FragColor = float4(color);\n"
3308 "}\n"
3309 "#endif // FRAGMENT_SHADER\n"
3310 "\n"
3311 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3312 "#endif // !MODE_DEFERREDGEOMETRY\n"
3313 "#endif // !MODE_WATER\n"
3314 "#endif // !MODE_REFRACTION\n"
3315 "#endif // !MODE_BLOOMBLUR\n"
3316 "#endif // !MODE_GENERIC\n"
3317 "#endif // !MODE_POSTPROCESS\n"
3318 "#endif // !MODE_SHOWDEPTH\n"
3319 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3320 ;
3321
3322 char *glslshaderstring = NULL;
3323 char *cgshaderstring = NULL;
3324 char *hlslshaderstring = NULL;
3325
3326 //=======================================================================================================================================================
3327
3328 typedef struct shaderpermutationinfo_s
3329 {
3330         const char *pretext;
3331         const char *name;
3332 }
3333 shaderpermutationinfo_t;
3334
3335 typedef struct shadermodeinfo_s
3336 {
3337         const char *vertexfilename;
3338         const char *geometryfilename;
3339         const char *fragmentfilename;
3340         const char *pretext;
3341         const char *name;
3342 }
3343 shadermodeinfo_t;
3344
3345 typedef enum shaderpermutation_e
3346 {
3347         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3348         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3349         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3350         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3351         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3352         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3353         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3354         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3355         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3356         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3357         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3358         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3359         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3360         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3361         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3362         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3363         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3364         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3365         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3366         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3367         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3368         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3369         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3370         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3371         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3372         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3373         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3374         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3375         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3376 }
3377 shaderpermutation_t;
3378
3379 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3380 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3381 {
3382         {"#define USEDIFFUSE\n", " diffuse"},
3383         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3384         {"#define USEVIEWTINT\n", " viewtint"},
3385         {"#define USECOLORMAPPING\n", " colormapping"},
3386         {"#define USESATURATION\n", " saturation"},
3387         {"#define USEFOGINSIDE\n", " foginside"},
3388         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3389         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3390         {"#define USEGAMMARAMPS\n", " gammaramps"},
3391         {"#define USECUBEFILTER\n", " cubefilter"},
3392         {"#define USEGLOW\n", " glow"},
3393         {"#define USEBLOOM\n", " bloom"},
3394         {"#define USESPECULAR\n", " specular"},
3395         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3396         {"#define USEREFLECTION\n", " reflection"},
3397         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3398         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3399         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3400         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3401         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3402         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3403         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3404         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3405         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3406         {"#define USEALPHAKILL\n", " alphakill"},
3407         {"#define USEREFLECTCUBE\n", " reflectcube"},
3408         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3409 };
3410
3411 // this enum selects which of the glslshadermodeinfo entries should be used
3412 typedef enum shadermode_e
3413 {
3414         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3415         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3416         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3417         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3418         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3419         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3420         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3421         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3422         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3423         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3424         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3425         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3426         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3427         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3428         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3429         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3430         SHADERMODE_COUNT
3431 }
3432 shadermode_t;
3433
3434 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3435 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3436 {
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3439         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3448         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3451         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3452         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3453 };
3454
3455 #ifdef SUPPORTCG
3456 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3457 {
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3467         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3468         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3469         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3470         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3471         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3472         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3473         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3474 };
3475 #endif
3476
3477 #ifdef SUPPORTD3D
3478 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3479 {
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3494         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3495         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3496 };
3497 #endif
3498
3499 struct r_glsl_permutation_s;
3500 typedef struct r_glsl_permutation_s
3501 {
3502         /// hash lookup data
3503         struct r_glsl_permutation_s *hashnext;
3504         unsigned int mode;
3505         unsigned int permutation;
3506
3507         /// indicates if we have tried compiling this permutation already
3508         qboolean compiled;
3509         /// 0 if compilation failed
3510         int program;
3511         /// locations of detected uniforms in program object, or -1 if not found
3512         int loc_Texture_First;
3513         int loc_Texture_Second;
3514         int loc_Texture_GammaRamps;
3515         int loc_Texture_Normal;
3516         int loc_Texture_Color;
3517         int loc_Texture_Gloss;
3518         int loc_Texture_Glow;
3519         int loc_Texture_SecondaryNormal;
3520         int loc_Texture_SecondaryColor;
3521         int loc_Texture_SecondaryGloss;
3522         int loc_Texture_SecondaryGlow;
3523         int loc_Texture_Pants;
3524         int loc_Texture_Shirt;
3525         int loc_Texture_FogHeightTexture;
3526         int loc_Texture_FogMask;
3527         int loc_Texture_Lightmap;
3528         int loc_Texture_Deluxemap;
3529         int loc_Texture_Attenuation;
3530         int loc_Texture_Cube;
3531         int loc_Texture_Refraction;
3532         int loc_Texture_Reflection;
3533         int loc_Texture_ShadowMap2D;
3534         int loc_Texture_CubeProjection;
3535         int loc_Texture_ScreenDepth;
3536         int loc_Texture_ScreenNormalMap;
3537         int loc_Texture_ScreenDiffuse;
3538         int loc_Texture_ScreenSpecular;
3539         int loc_Texture_ReflectMask;
3540         int loc_Texture_ReflectCube;
3541         int loc_Alpha;
3542         int loc_BloomBlur_Parameters;
3543         int loc_ClientTime;
3544         int loc_Color_Ambient;
3545         int loc_Color_Diffuse;
3546         int loc_Color_Specular;
3547         int loc_Color_Glow;
3548         int loc_Color_Pants;
3549         int loc_Color_Shirt;
3550         int loc_DeferredColor_Ambient;
3551         int loc_DeferredColor_Diffuse;
3552         int loc_DeferredColor_Specular;
3553         int loc_DeferredMod_Diffuse;
3554         int loc_DeferredMod_Specular;
3555         int loc_DistortScaleRefractReflect;
3556         int loc_EyePosition;
3557         int loc_FogColor;
3558         int loc_FogHeightFade;
3559         int loc_FogPlane;
3560         int loc_FogPlaneViewDist;
3561         int loc_FogRangeRecip;
3562         int loc_LightColor;
3563         int loc_LightDir;
3564         int loc_LightPosition;
3565         int loc_OffsetMapping_Scale;
3566         int loc_PixelSize;
3567         int loc_ReflectColor;
3568         int loc_ReflectFactor;
3569         int loc_ReflectOffset;
3570         int loc_RefractColor;
3571         int loc_Saturation;
3572         int loc_ScreenCenterRefractReflect;
3573         int loc_ScreenScaleRefractReflect;
3574         int loc_ScreenToDepth;
3575         int loc_ShadowMap_Parameters;
3576         int loc_ShadowMap_TextureScale;
3577         int loc_SpecularPower;
3578         int loc_UserVec1;
3579         int loc_UserVec2;
3580         int loc_UserVec3;
3581         int loc_UserVec4;
3582         int loc_ViewTintColor;
3583         int loc_ViewToLight;
3584         int loc_ModelToLight;
3585         int loc_TexMatrix;
3586         int loc_BackgroundTexMatrix;
3587         int loc_ModelViewProjectionMatrix;
3588         int loc_ModelViewMatrix;
3589         int loc_PixelToScreenTexCoord;
3590         int loc_ModelToReflectCube;
3591         int loc_ShadowMapMatrix;
3592         int loc_BloomColorSubtract;
3593         int loc_NormalmapScrollBlend;
3594 }
3595 r_glsl_permutation_t;
3596
3597 #define SHADERPERMUTATION_HASHSIZE 256
3598
3599
3600 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3601 // these can NOT degrade! only use for simple stuff
3602 enum
3603 {
3604         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3605         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3606         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3607         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3608         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3609         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3610 };
3611 #define SHADERSTATICPARMS_COUNT 6
3612
3613 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3614 static int shaderstaticparms_count = 0;
3615
3616 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3617 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3618 qboolean R_CompileShader_CheckStaticParms(void)
3619 {
3620         static int r_compileshader_staticparms_save[1];
3621         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3622         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3623
3624         // detect all
3625         if (r_glsl_saturation_redcompensate.integer)
3626                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3627         if (r_shadow_glossexact.integer)
3628                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3629         if (r_glsl_postprocess.integer)
3630         {
3631                 if (r_glsl_postprocess_uservec1_enable.integer)
3632                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3633                 if (r_glsl_postprocess_uservec2_enable.integer)
3634                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3635                 if (r_glsl_postprocess_uservec3_enable.integer)
3636                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3637                 if (r_glsl_postprocess_uservec4_enable.integer)
3638                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3639         }
3640         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3641 }
3642
3643 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3644         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3645                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3646         else \
3647                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3648 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3649 {
3650         shaderstaticparms_count = 0;
3651
3652         // emit all
3653         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3654         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3655         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3656         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3657         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3658         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3659 }
3660
3661 /// information about each possible shader permutation
3662 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3663 /// currently selected permutation
3664 r_glsl_permutation_t *r_glsl_permutation;
3665 /// storage for permutations linked in the hash table
3666 memexpandablearray_t r_glsl_permutationarray;
3667
3668 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3669 {
3670         //unsigned int hashdepth = 0;
3671         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3672         r_glsl_permutation_t *p;
3673         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3674         {
3675                 if (p->mode == mode && p->permutation == permutation)
3676                 {
3677                         //if (hashdepth > 10)
3678                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3679                         return p;
3680                 }
3681                 //hashdepth++;
3682         }
3683         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3684         p->mode = mode;
3685         p->permutation = permutation;
3686         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3687         r_glsl_permutationhash[mode][hashindex] = p;
3688         //if (hashdepth > 10)
3689         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3690         return p;
3691 }
3692
3693 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3694 {
3695         char *shaderstring;
3696         if (!filename || !filename[0])
3697                 return NULL;
3698         if (!strcmp(filename, "glsl/default.glsl"))
3699         {
3700                 if (!glslshaderstring)
3701                 {
3702                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703                         if (glslshaderstring)
3704                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3705                         else
3706                                 glslshaderstring = (char *)builtinshaderstring;
3707                 }
3708                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3709                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3710                 return shaderstring;
3711         }
3712         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3713         if (shaderstring)
3714         {
3715                 if (printfromdisknotice)
3716                         Con_DPrintf("from disk %s... ", filename);
3717                 return shaderstring;
3718         }
3719         return shaderstring;
3720 }
3721
3722 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3723 {
3724         int i;
3725         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3726         char *vertexstring, *geometrystring, *fragmentstring;
3727         char permutationname[256];
3728         int vertstrings_count = 0;
3729         int geomstrings_count = 0;
3730         int fragstrings_count = 0;
3731         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3733         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3734
3735         if (p->compiled)
3736                 return;
3737         p->compiled = true;
3738         p->program = 0;
3739
3740         permutationname[0] = 0;
3741         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3742         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3743         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3744
3745         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3746
3747         // the first pretext is which type of shader to compile as
3748         // (later these will all be bound together as a program object)
3749         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3750         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3751         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3752
3753         // the second pretext is the mode (for example a light source)
3754         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3755         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3756         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3757         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3758
3759         // now add all the permutation pretexts
3760         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3761         {
3762                 if (permutation & (1<<i))
3763                 {
3764                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3765                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3766                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3767                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3768                 }
3769                 else
3770                 {
3771                         // keep line numbers correct
3772                         vertstrings_list[vertstrings_count++] = "\n";
3773                         geomstrings_list[geomstrings_count++] = "\n";
3774                         fragstrings_list[fragstrings_count++] = "\n";
3775                 }
3776         }
3777
3778         // add static parms
3779         R_CompileShader_AddStaticParms(mode, permutation);
3780         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3781         vertstrings_count += shaderstaticparms_count;
3782         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3783         geomstrings_count += shaderstaticparms_count;
3784         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3785         fragstrings_count += shaderstaticparms_count;
3786
3787         // now append the shader text itself
3788         vertstrings_list[vertstrings_count++] = vertexstring;
3789         geomstrings_list[geomstrings_count++] = geometrystring;
3790         fragstrings_list[fragstrings_count++] = fragmentstring;
3791
3792         // if any sources were NULL, clear the respective list
3793         if (!vertexstring)
3794                 vertstrings_count = 0;
3795         if (!geometrystring)
3796                 geomstrings_count = 0;
3797         if (!fragmentstring)
3798                 fragstrings_count = 0;
3799
3800         // compile the shader program
3801         if (vertstrings_count + geomstrings_count + fragstrings_count)
3802                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3803         if (p->program)
3804         {
3805                 CHECKGLERROR
3806                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3807                 // look up all the uniform variable names we care about, so we don't
3808                 // have to look them up every time we set them
3809
3810                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3811                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3812                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3813                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3814                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3815                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3816                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3817                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3818                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3819                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3820                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3821                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3822                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3823                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3824                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3825                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3826                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3827                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3828                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3829                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3830                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3831                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3832                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3833                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3834                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3835                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3836                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3837                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3838                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3839                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3840                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3841                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3842                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3843                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3844                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3845                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3846                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3847                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3848                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3849                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3850                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3851                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3852                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3853                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3854                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3855                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3856                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3857                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3858                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3859                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3860                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3861                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3862                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3863                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3864                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3865                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3866                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3867                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3868                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3869                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3870                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3871                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3872                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3873                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3874                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3875                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3876                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3877                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3878                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3879                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3880                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3881                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3882                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3883                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3884                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3885                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3886                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3887                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3888                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3889                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3890                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3891                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3892                 // initialize the samplers to refer to the texture units we use
3893                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3894                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3895                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3896                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3897                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3898                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3899                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3900                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3901                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3902                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3903                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3904                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3905                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3906                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3907                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3908                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3909                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3910                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3911                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3912                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3913                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3914                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3915                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3916                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3917                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3918                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3919                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3920                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3921                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3922                 CHECKGLERROR
3923                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3924         }
3925         else
3926                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3927
3928         // free the strings
3929         if (vertexstring)
3930                 Mem_Free(vertexstring);
3931         if (geometrystring)
3932                 Mem_Free(geometrystring);
3933         if (fragmentstring)
3934                 Mem_Free(fragmentstring);
3935 }
3936
3937 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3938 {
3939         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3940         if (r_glsl_permutation != perm)
3941         {
3942                 r_glsl_permutation = perm;
3943                 if (!r_glsl_permutation->program)
3944                 {
3945                         if (!r_glsl_permutation->compiled)
3946                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3947                         if (!r_glsl_permutation->program)
3948                         {
3949                                 // remove features until we find a valid permutation
3950                                 int i;
3951                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3952                                 {
3953                                         // reduce i more quickly whenever it would not remove any bits
3954                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3955                                         if (!(permutation & j))
3956                                                 continue;
3957                                         permutation -= j;
3958                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3959                                         if (!r_glsl_permutation->compiled)
3960                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3961                                         if (r_glsl_permutation->program)
3962                                                 break;
3963                                 }
3964                                 if (i >= SHADERPERMUTATION_COUNT)
3965                                 {
3966                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3967                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3968                                         qglUseProgramObjectARB(0);CHECKGLERROR
3969                                         return; // no bit left to clear, entire mode is broken
3970                                 }
3971                         }
3972                 }
3973                 CHECKGLERROR
3974                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3975         }
3976         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3977         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3978         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3979 }
3980
3981 #ifdef SUPPORTCG
3982 #include <Cg/cgGL.h>
3983 struct r_cg_permutation_s;
3984 typedef struct r_cg_permutation_s
3985 {
3986         /// hash lookup data
3987         struct r_cg_permutation_s *hashnext;
3988         unsigned int mode;
3989         unsigned int permutation;
3990
3991         /// indicates if we have tried compiling this permutation already
3992         qboolean compiled;
3993         /// 0 if compilation failed
3994         CGprogram vprogram;
3995         CGprogram fprogram;
3996         /// locations of detected parameters in programs, or NULL if not found
3997         CGparameter vp_EyePosition;
3998         CGparameter vp_FogPlane;
3999         CGparameter vp_LightDir;
4000         CGparameter vp_LightPosition;
4001         CGparameter vp_ModelToLight;
4002         CGparameter vp_TexMatrix;
4003         CGparameter vp_BackgroundTexMatrix;
4004         CGparameter vp_ModelViewProjectionMatrix;
4005         CGparameter vp_ModelViewMatrix;
4006         CGparameter vp_ShadowMapMatrix;
4007
4008         CGparameter fp_Texture_First;
4009         CGparameter fp_Texture_Second;
4010         CGparameter fp_Texture_GammaRamps;
4011         CGparameter fp_Texture_Normal;
4012         CGparameter fp_Texture_Color;
4013         CGparameter fp_Texture_Gloss;
4014         CGparameter fp_Texture_Glow;
4015         CGparameter fp_Texture_SecondaryNormal;
4016         CGparameter fp_Texture_SecondaryColor;
4017         CGparameter fp_Texture_SecondaryGloss;
4018         CGparameter fp_Texture_SecondaryGlow;
4019         CGparameter fp_Texture_Pants;
4020         CGparameter fp_Texture_Shirt;
4021         CGparameter fp_Texture_FogHeightTexture;
4022         CGparameter fp_Texture_FogMask;
4023         CGparameter fp_Texture_Lightmap;
4024         CGparameter fp_Texture_Deluxemap;
4025         CGparameter fp_Texture_Attenuation;
4026         CGparameter fp_Texture_Cube;
4027         CGparameter fp_Texture_Refraction;
4028         CGparameter fp_Texture_Reflection;
4029         CGparameter fp_Texture_ShadowMap2D;
4030         CGparameter fp_Texture_CubeProjection;
4031         CGparameter fp_Texture_ScreenDepth;
4032         CGparameter fp_Texture_ScreenNormalMap;
4033         CGparameter fp_Texture_ScreenDiffuse;
4034         CGparameter fp_Texture_ScreenSpecular;
4035         CGparameter fp_Texture_ReflectMask;
4036         CGparameter fp_Texture_ReflectCube;
4037         CGparameter fp_Alpha;
4038         CGparameter fp_BloomBlur_Parameters;
4039         CGparameter fp_ClientTime;
4040         CGparameter fp_Color_Ambient;
4041         CGparameter fp_Color_Diffuse;
4042         CGparameter fp_Color_Specular;
4043         CGparameter fp_Color_Glow;
4044         CGparameter fp_Color_Pants;
4045         CGparameter fp_Color_Shirt;
4046         CGparameter fp_DeferredColor_Ambient;
4047         CGparameter fp_DeferredColor_Diffuse;
4048         CGparameter fp_DeferredColor_Specular;
4049         CGparameter fp_DeferredMod_Diffuse;
4050         CGparameter fp_DeferredMod_Specular;
4051         CGparameter fp_DistortScaleRefractReflect;
4052         CGparameter fp_EyePosition;
4053         CGparameter fp_FogColor;
4054         CGparameter fp_FogHeightFade;
4055         CGparameter fp_FogPlane;
4056         CGparameter fp_FogPlaneViewDist;
4057         CGparameter fp_FogRangeRecip;
4058         CGparameter fp_LightColor;
4059         CGparameter fp_LightDir;
4060         CGparameter fp_LightPosition;
4061         CGparameter fp_OffsetMapping_Scale;
4062         CGparameter fp_PixelSize;
4063         CGparameter fp_ReflectColor;
4064         CGparameter fp_ReflectFactor;
4065         CGparameter fp_ReflectOffset;
4066         CGparameter fp_RefractColor;
4067         CGparameter fp_Saturation;
4068         CGparameter fp_ScreenCenterRefractReflect;
4069         CGparameter fp_ScreenScaleRefractReflect;
4070         CGparameter fp_ScreenToDepth;
4071         CGparameter fp_ShadowMap_Parameters;
4072         CGparameter fp_ShadowMap_TextureScale;
4073         CGparameter fp_SpecularPower;
4074         CGparameter fp_UserVec1;
4075         CGparameter fp_UserVec2;
4076         CGparameter fp_UserVec3;
4077         CGparameter fp_UserVec4;
4078         CGparameter fp_ViewTintColor;
4079         CGparameter fp_ViewToLight;
4080         CGparameter fp_PixelToScreenTexCoord;
4081         CGparameter fp_ModelToReflectCube;
4082         CGparameter fp_BloomColorSubtract;
4083         CGparameter fp_NormalmapScrollBlend;
4084 }
4085 r_cg_permutation_t;
4086
4087 /// information about each possible shader permutation
4088 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4089 /// currently selected permutation
4090 r_cg_permutation_t *r_cg_permutation;
4091 /// storage for permutations linked in the hash table
4092 memexpandablearray_t r_cg_permutationarray;
4093
4094 #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));}}
4095
4096 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4097 {
4098         //unsigned int hashdepth = 0;
4099         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4100         r_cg_permutation_t *p;
4101         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4102         {
4103                 if (p->mode == mode && p->permutation == permutation)
4104                 {
4105                         //if (hashdepth > 10)
4106                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4107                         return p;
4108                 }
4109                 //hashdepth++;
4110         }
4111         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4112         p->mode = mode;
4113         p->permutation = permutation;
4114         p->hashnext = r_cg_permutationhash[mode][hashindex];
4115         r_cg_permutationhash[mode][hashindex] = p;
4116         //if (hashdepth > 10)
4117         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4118         return p;
4119 }
4120
4121 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4122 {
4123         char *shaderstring;
4124         if (!filename || !filename[0])
4125                 return NULL;
4126         if (!strcmp(filename, "cg/default.cg"))
4127         {
4128                 if (!cgshaderstring)
4129                 {
4130                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4131                         if (cgshaderstring)
4132                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4133                         else
4134                                 cgshaderstring = (char *)builtincgshaderstring;
4135                 }
4136                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4137                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4138                 return shaderstring;
4139         }
4140         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4141         if (shaderstring)
4142         {
4143                 if (printfromdisknotice)
4144                         Con_DPrintf("from disk %s... ", filename);
4145                 return shaderstring;
4146         }
4147         return shaderstring;
4148 }
4149
4150 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4151 {
4152         // TODO: load or create .fp and .vp shader files
4153 }
4154
4155 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4156 {
4157         int i;
4158         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4159         int vertstring_length = 0;
4160         int geomstring_length = 0;
4161         int fragstring_length = 0;
4162         char *t;
4163         char *vertexstring, *geometrystring, *fragmentstring;
4164         char *vertstring, *geomstring, *fragstring;
4165         char permutationname[256];
4166         char cachename[256];
4167         CGprofile vertexProfile;
4168         CGprofile fragmentProfile;
4169         int vertstrings_count = 0;
4170         int geomstrings_count = 0;
4171         int fragstrings_count = 0;
4172         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4174         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4175
4176         if (p->compiled)
4177                 return;
4178         p->compiled = true;
4179         p->vprogram = NULL;
4180         p->fprogram = NULL;
4181
4182         permutationname[0] = 0;
4183         cachename[0] = 0;
4184         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4185         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4186         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4187
4188         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4189         strlcat(cachename, "cg/", sizeof(cachename));
4190
4191         // the first pretext is which type of shader to compile as
4192         // (later these will all be bound together as a program object)
4193         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4194         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4195         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4196
4197         // the second pretext is the mode (for example a light source)
4198         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4199         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4200         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4201         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4202         strlcat(cachename, modeinfo->name, sizeof(cachename));
4203
4204         // now add all the permutation pretexts
4205         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206         {
4207                 if (permutation & (1<<i))
4208                 {
4209                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4211                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4212                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4213                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4214                 }
4215                 else
4216                 {
4217                         // keep line numbers correct
4218                         vertstrings_list[vertstrings_count++] = "\n";
4219                         geomstrings_list[geomstrings_count++] = "\n";
4220                         fragstrings_list[fragstrings_count++] = "\n";
4221                 }
4222         }
4223
4224         // add static parms
4225         R_CompileShader_AddStaticParms(mode, permutation);
4226         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4227         vertstrings_count += shaderstaticparms_count;
4228         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4229         geomstrings_count += shaderstaticparms_count;
4230         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4231         fragstrings_count += shaderstaticparms_count;
4232
4233         // replace spaces in the cachename with _ characters
4234         for (i = 0;cachename[i];i++)
4235                 if (cachename[i] == ' ')
4236                         cachename[i] = '_';
4237
4238         // now append the shader text itself
4239         vertstrings_list[vertstrings_count++] = vertexstring;
4240         geomstrings_list[geomstrings_count++] = geometrystring;
4241         fragstrings_list[fragstrings_count++] = fragmentstring;
4242
4243         // if any sources were NULL, clear the respective list
4244         if (!vertexstring)
4245                 vertstrings_count = 0;
4246         if (!geometrystring)
4247                 geomstrings_count = 0;
4248         if (!fragmentstring)
4249                 fragstrings_count = 0;
4250
4251         vertstring_length = 0;
4252         for (i = 0;i < vertstrings_count;i++)
4253                 vertstring_length += strlen(vertstrings_list[i]);
4254         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4255         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4256                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4257
4258         geomstring_length = 0;
4259         for (i = 0;i < geomstrings_count;i++)
4260                 geomstring_length += strlen(geomstrings_list[i]);
4261         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4262         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4263                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4264
4265         fragstring_length = 0;
4266         for (i = 0;i < fragstrings_count;i++)
4267                 fragstring_length += strlen(fragstrings_list[i]);
4268         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4269         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4270                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4271
4272         CHECKGLERROR
4273         CHECKCGERROR
4274         //vertexProfile = CG_PROFILE_ARBVP1;
4275         //fragmentProfile = CG_PROFILE_ARBFP1;
4276         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4277         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4278         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4279         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4280         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4281         CHECKGLERROR
4282
4283         // try to load the cached shader, or generate one
4284         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4285
4286         // if caching failed, do a dynamic compile for now
4287         CHECKCGERROR
4288         if (vertstring[0] && !p->vprogram)
4289                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4290         CHECKCGERROR
4291         if (fragstring[0] && !p->fprogram)
4292                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4293         CHECKCGERROR
4294
4295         // look up all the uniform variable names we care about, so we don't
4296         // have to look them up every time we set them
4297         if (p->vprogram)
4298         {
4299                 CHECKCGERROR
4300                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4301                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4302                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4303                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4304                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4305                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4306                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4307                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4308                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4309                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4310                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4311                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4312                 CHECKCGERROR
4313         }
4314         if (p->fprogram)
4315         {
4316                 CHECKCGERROR
4317                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4318                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4319                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4320                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4321                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4322                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4323                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4324                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4325                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4326                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4327                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4328                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4329                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4330                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4331                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4332                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4333                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4334                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4335                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4336                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4337                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4338                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4339                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4340                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4341                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4342                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4343                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4344                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4345                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4346                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4347                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4348                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4349                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4350                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4351                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4352                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4353                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4354                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4355                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4356                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4357                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4358                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4359                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4360                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4361                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4362                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4363                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4364                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4365                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4366                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4367                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4368                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4369                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4370                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4371                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4372                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4373                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4374                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4375                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4376                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4377                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4378                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4379                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4380                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4381                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4382                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4383                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4384                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4385                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4386                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4387                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4388                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4389                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4390                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4391                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4392                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4393                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4394                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4395                 CHECKCGERROR
4396         }
4397
4398         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4399                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4400         else
4401                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4402
4403         // free the strings
4404         if (vertstring)
4405                 Mem_Free(vertstring);
4406         if (geomstring)
4407                 Mem_Free(geomstring);
4408         if (fragstring)
4409                 Mem_Free(fragstring);
4410         if (vertexstring)
4411                 Mem_Free(vertexstring);
4412         if (geometrystring)
4413                 Mem_Free(geometrystring);
4414         if (fragmentstring)
4415                 Mem_Free(fragmentstring);
4416 }
4417
4418 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4419 {
4420         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4421         CHECKGLERROR
4422         CHECKCGERROR
4423         if (r_cg_permutation != perm)
4424         {
4425                 r_cg_permutation = perm;
4426                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4427                 {
4428                         if (!r_cg_permutation->compiled)
4429                                 R_CG_CompilePermutation(perm, mode, permutation);
4430                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4431                         {
4432                                 // remove features until we find a valid permutation
4433                                 int i;
4434                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4435                                 {
4436                                         // reduce i more quickly whenever it would not remove any bits
4437                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4438                                         if (!(permutation & j))
4439                                                 continue;
4440                                         permutation -= j;
4441                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4442                                         if (!r_cg_permutation->compiled)
4443                                                 R_CG_CompilePermutation(perm, mode, permutation);
4444                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4445                                                 break;
4446                                 }
4447                                 if (i >= SHADERPERMUTATION_COUNT)
4448                                 {
4449                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4450                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4451                                         return; // no bit left to clear, entire mode is broken
4452                                 }
4453                         }
4454                 }
4455                 CHECKGLERROR
4456                 CHECKCGERROR
4457                 if (r_cg_permutation->vprogram)
4458                 {
4459                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4460                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4461                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4462                 }
4463                 else
4464                 {
4465                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4467                 }
4468                 if (r_cg_permutation->fprogram)
4469                 {
4470                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4471                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4472                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4473                 }
4474                 else
4475                 {
4476                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4477                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4478                 }
4479         }
4480         CHECKCGERROR
4481         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4482         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4483         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4484 }
4485
4486 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4487 {
4488         cgGLSetTextureParameter(param, R_GetTexture(tex));
4489         cgGLEnableTextureParameter(param);
4490 }
4491 #endif
4492
4493 #ifdef SUPPORTD3D
4494
4495 #ifdef SUPPORTD3D
4496 #include <d3d9.h>
4497 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4498 extern D3DCAPS9 vid_d3d9caps;
4499 #endif
4500
4501 struct r_hlsl_permutation_s;
4502 typedef struct r_hlsl_permutation_s
4503 {
4504         /// hash lookup data
4505         struct r_hlsl_permutation_s *hashnext;
4506         unsigned int mode;
4507         unsigned int permutation;
4508
4509         /// indicates if we have tried compiling this permutation already
4510         qboolean compiled;
4511         /// NULL if compilation failed
4512         IDirect3DVertexShader9 *vertexshader;
4513         IDirect3DPixelShader9 *pixelshader;
4514 }
4515 r_hlsl_permutation_t;
4516
4517 typedef enum D3DVSREGISTER_e
4518 {
4519         D3DVSREGISTER_TexMatrix = 0, // float4x4
4520         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4521         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4522         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4523         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4524         D3DVSREGISTER_ModelToLight = 20, // float4x4
4525         D3DVSREGISTER_EyePosition = 24,
4526         D3DVSREGISTER_FogPlane = 25,
4527         D3DVSREGISTER_LightDir = 26,
4528         D3DVSREGISTER_LightPosition = 27,
4529 }
4530 D3DVSREGISTER_t;
4531
4532 typedef enum D3DPSREGISTER_e
4533 {
4534         D3DPSREGISTER_Alpha = 0,
4535         D3DPSREGISTER_BloomBlur_Parameters = 1,
4536         D3DPSREGISTER_ClientTime = 2,
4537         D3DPSREGISTER_Color_Ambient = 3,
4538         D3DPSREGISTER_Color_Diffuse = 4,
4539         D3DPSREGISTER_Color_Specular = 5,
4540         D3DPSREGISTER_Color_Glow = 6,
4541         D3DPSREGISTER_Color_Pants = 7,
4542         D3DPSREGISTER_Color_Shirt = 8,
4543         D3DPSREGISTER_DeferredColor_Ambient = 9,
4544         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4545         D3DPSREGISTER_DeferredColor_Specular = 11,
4546         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4547         D3DPSREGISTER_DeferredMod_Specular = 13,
4548         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4549         D3DPSREGISTER_EyePosition = 15, // unused
4550         D3DPSREGISTER_FogColor = 16,
4551         D3DPSREGISTER_FogHeightFade = 17,
4552         D3DPSREGISTER_FogPlane = 18,
4553         D3DPSREGISTER_FogPlaneViewDist = 19,
4554         D3DPSREGISTER_FogRangeRecip = 20,
4555         D3DPSREGISTER_LightColor = 21,
4556         D3DPSREGISTER_LightDir = 22, // unused
4557         D3DPSREGISTER_LightPosition = 23,
4558         D3DPSREGISTER_OffsetMapping_Scale = 24,
4559         D3DPSREGISTER_PixelSize = 25,
4560         D3DPSREGISTER_ReflectColor = 26,
4561         D3DPSREGISTER_ReflectFactor = 27,
4562         D3DPSREGISTER_ReflectOffset = 28,
4563         D3DPSREGISTER_RefractColor = 29,
4564         D3DPSREGISTER_Saturation = 30,
4565         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4566         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4567         D3DPSREGISTER_ScreenToDepth = 33,
4568         D3DPSREGISTER_ShadowMap_Parameters = 34,
4569         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4570         D3DPSREGISTER_SpecularPower = 36,
4571         D3DPSREGISTER_UserVec1 = 37,
4572         D3DPSREGISTER_UserVec2 = 38,
4573         D3DPSREGISTER_UserVec3 = 39,
4574         D3DPSREGISTER_UserVec4 = 40,
4575         D3DPSREGISTER_ViewTintColor = 41,
4576         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4577         D3DPSREGISTER_BloomColorSubtract = 43,
4578         D3DPSREGISTER_ViewToLight = 44, // float4x4
4579         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4580         D3DPSREGISTER_NormalmapScrollBlend = 52,
4581         // next at 53
4582 }
4583 D3DPSREGISTER_t;
4584
4585 /// information about each possible shader permutation
4586 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4587 /// currently selected permutation
4588 r_hlsl_permutation_t *r_hlsl_permutation;
4589 /// storage for permutations linked in the hash table
4590 memexpandablearray_t r_hlsl_permutationarray;
4591
4592 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4593 {
4594         //unsigned int hashdepth = 0;
4595         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4596         r_hlsl_permutation_t *p;
4597         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4598         {
4599                 if (p->mode == mode && p->permutation == permutation)
4600                 {
4601                         //if (hashdepth > 10)
4602                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4603                         return p;
4604                 }
4605                 //hashdepth++;
4606         }
4607         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4608         p->mode = mode;
4609         p->permutation = permutation;
4610         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4611         r_hlsl_permutationhash[mode][hashindex] = p;
4612         //if (hashdepth > 10)
4613         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4614         return p;
4615 }
4616
4617 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4618 {
4619         char *shaderstring;
4620         if (!filename || !filename[0])
4621                 return NULL;
4622         if (!strcmp(filename, "hlsl/default.hlsl"))
4623         {
4624                 if (!hlslshaderstring)
4625                 {
4626                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4627                         if (hlslshaderstring)
4628                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4629                         else
4630                                 hlslshaderstring = (char *)builtincgshaderstring;
4631                 }
4632                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4633                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4634                 return shaderstring;
4635         }
4636         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4637         if (shaderstring)
4638         {
4639                 if (printfromdisknotice)
4640                         Con_DPrintf("from disk %s... ", filename);
4641                 return shaderstring;
4642         }
4643         return shaderstring;
4644 }
4645
4646 #include <d3dx9.h>
4647 //#include <d3dx9shader.h>
4648 //#include <d3dx9mesh.h>
4649
4650 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4651 {
4652         DWORD *vsbin = NULL;
4653         DWORD *psbin = NULL;
4654         fs_offset_t vsbinsize;
4655         fs_offset_t psbinsize;
4656 //      IDirect3DVertexShader9 *vs = NULL;
4657 //      IDirect3DPixelShader9 *ps = NULL;
4658         ID3DXBuffer *vslog = NULL;
4659         ID3DXBuffer *vsbuffer = NULL;
4660         ID3DXConstantTable *vsconstanttable = NULL;
4661         ID3DXBuffer *pslog = NULL;
4662         ID3DXBuffer *psbuffer = NULL;
4663         ID3DXConstantTable *psconstanttable = NULL;
4664         int vsresult = 0;
4665         int psresult = 0;
4666         char temp[MAX_INPUTLINE];
4667         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4668         qboolean debugshader = gl_paranoid.integer != 0;
4669         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4670         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4671         if (!debugshader)
4672         {
4673                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4674                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4675         }
4676         if ((!vsbin && vertstring) || (!psbin && fragstring))
4677         {
4678                 const char* dllnames_d3dx9 [] =
4679                 {
4680                         "d3dx9_43.dll",
4681                         "d3dx9_42.dll",
4682                         "d3dx9_41.dll",
4683                         "d3dx9_40.dll",
4684                         "d3dx9_39.dll",
4685                         "d3dx9_38.dll",
4686                         "d3dx9_37.dll",
4687                         "d3dx9_36.dll",
4688                         "d3dx9_35.dll",
4689                         "d3dx9_34.dll",
4690                         "d3dx9_33.dll",
4691                         "d3dx9_32.dll",
4692                         "d3dx9_31.dll",
4693                         "d3dx9_30.dll",
4694                         "d3dx9_29.dll",
4695                         "d3dx9_28.dll",
4696                         "d3dx9_27.dll",
4697                         "d3dx9_26.dll",
4698                         "d3dx9_25.dll",
4699                         "d3dx9_24.dll",
4700                         NULL
4701                 };
4702                 dllhandle_t d3dx9_dll = NULL;
4703                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4704                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4705                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4706                 dllfunction_t d3dx9_dllfuncs[] =
4707                 {
4708                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4709                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4710                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4711                         {NULL, NULL}
4712                 };
4713                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4714                 {
4715                         DWORD shaderflags = 0;
4716                         if (debugshader)
4717                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4718                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4719                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4720                         if (vertstring && vertstring[0])
4721                         {
4722                                 if (debugshader)
4723                                 {
4724 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4725 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4726                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4727                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4728                                 }
4729                                 else
4730                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4731                                 if (vsbuffer)
4732                                 {
4733                                         vsbinsize = vsbuffer->GetBufferSize();
4734                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4735                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4736                                         vsbuffer->Release();
4737                                 }
4738                                 if (vslog)
4739                                 {
4740                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4741                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4742                                         vslog->Release();
4743                                 }
4744                         }
4745                         if (fragstring && fragstring[0])
4746                         {
4747                                 if (debugshader)
4748                                 {
4749 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4750 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4751                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4752                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4753                                 }
4754                                 else
4755                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4756                                 if (psbuffer)
4757                                 {
4758                                         psbinsize = psbuffer->GetBufferSize();
4759                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4760                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4761                                         psbuffer->Release();
4762                                 }
4763                                 if (pslog)
4764                                 {
4765                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4766                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4767                                         pslog->Release();
4768                                 }
4769                         }
4770                         Sys_UnloadLibrary(&d3dx9_dll);
4771                 }
4772                 else
4773                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4774         }
4775         if (vsbin && psbin)
4776         {
4777                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4778                 if (FAILED(vsresult))
4779                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4780                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4781                 if (FAILED(psresult))
4782                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4783         }
4784         // free the shader data
4785         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4786         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4787 }
4788
4789 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4790 {
4791         int i;
4792         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4793         int vertstring_length = 0;
4794         int geomstring_length = 0;
4795         int fragstring_length = 0;
4796         char *t;
4797         char *vertexstring, *geometrystring, *fragmentstring;
4798         char *vertstring, *geomstring, *fragstring;
4799         char permutationname[256];
4800         char cachename[256];
4801         int vertstrings_count = 0;
4802         int geomstrings_count = 0;
4803         int fragstrings_count = 0;
4804         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4806         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4807
4808         if (p->compiled)
4809                 return;
4810         p->compiled = true;
4811         p->vertexshader = NULL;
4812         p->pixelshader = NULL;
4813
4814         permutationname[0] = 0;
4815         cachename[0] = 0;
4816         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4817         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4818         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4819
4820         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4821         strlcat(cachename, "hlsl/", sizeof(cachename));
4822
4823         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4824         vertstrings_count = 0;
4825         geomstrings_count = 0;
4826         fragstrings_count = 0;
4827         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4828         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4829         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4830
4831         // the first pretext is which type of shader to compile as
4832         // (later these will all be bound together as a program object)
4833         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4834         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4835         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4836
4837         // the second pretext is the mode (for example a light source)
4838         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4839         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4840         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4841         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4842         strlcat(cachename, modeinfo->name, sizeof(cachename));
4843
4844         // now add all the permutation pretexts
4845         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4846         {
4847                 if (permutation & (1<<i))
4848                 {
4849                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4851                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4852                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4853                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4854                 }
4855                 else
4856                 {
4857                         // keep line numbers correct
4858                         vertstrings_list[vertstrings_count++] = "\n";
4859                         geomstrings_list[geomstrings_count++] = "\n";
4860                         fragstrings_list[fragstrings_count++] = "\n";
4861                 }
4862         }
4863
4864         // add static parms
4865         R_CompileShader_AddStaticParms(mode, permutation);
4866         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4867         vertstrings_count += shaderstaticparms_count;
4868         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4869         geomstrings_count += shaderstaticparms_count;
4870         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4871         fragstrings_count += shaderstaticparms_count;
4872
4873         // replace spaces in the cachename with _ characters
4874         for (i = 0;cachename[i];i++)
4875                 if (cachename[i] == ' ')
4876                         cachename[i] = '_';
4877
4878         // now append the shader text itself
4879         vertstrings_list[vertstrings_count++] = vertexstring;
4880         geomstrings_list[geomstrings_count++] = geometrystring;
4881         fragstrings_list[fragstrings_count++] = fragmentstring;
4882
4883         // if any sources were NULL, clear the respective list
4884         if (!vertexstring)
4885                 vertstrings_count = 0;
4886         if (!geometrystring)
4887                 geomstrings_count = 0;
4888         if (!fragmentstring)
4889                 fragstrings_count = 0;
4890
4891         vertstring_length = 0;
4892         for (i = 0;i < vertstrings_count;i++)
4893                 vertstring_length += strlen(vertstrings_list[i]);
4894         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4895         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4896                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4897
4898         geomstring_length = 0;
4899         for (i = 0;i < geomstrings_count;i++)
4900                 geomstring_length += strlen(geomstrings_list[i]);
4901         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4902         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4903                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4904
4905         fragstring_length = 0;
4906         for (i = 0;i < fragstrings_count;i++)
4907                 fragstring_length += strlen(fragstrings_list[i]);
4908         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4909         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4910                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4911
4912         // try to load the cached shader, or generate one
4913         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4914
4915         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4916                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4917         else
4918                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4919
4920         // free the strings
4921         if (vertstring)
4922                 Mem_Free(vertstring);
4923         if (geomstring)
4924                 Mem_Free(geomstring);
4925         if (fragstring)
4926                 Mem_Free(fragstring);
4927         if (vertexstring)
4928                 Mem_Free(vertexstring);
4929         if (geometrystring)
4930                 Mem_Free(geometrystring);
4931         if (fragmentstring)
4932                 Mem_Free(fragmentstring);
4933 }
4934
4935 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4936 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4937 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);}
4938 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);}
4939 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);}
4940 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);}
4941
4942 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4943 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4944 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);}
4945 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);}
4946 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);}
4947 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);}
4948
4949 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4950 {
4951         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4952         if (r_hlsl_permutation != perm)
4953         {
4954                 r_hlsl_permutation = perm;
4955                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4956                 {
4957                         if (!r_hlsl_permutation->compiled)
4958                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4959                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4960                         {
4961                                 // remove features until we find a valid permutation
4962                                 int i;
4963                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4964                                 {
4965                                         // reduce i more quickly whenever it would not remove any bits
4966                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4967                                         if (!(permutation & j))
4968                                                 continue;
4969                                         permutation -= j;
4970                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4971                                         if (!r_hlsl_permutation->compiled)
4972                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4973                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4974                                                 break;
4975                                 }
4976                                 if (i >= SHADERPERMUTATION_COUNT)
4977                                 {
4978                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4979                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4980                                         return; // no bit left to clear, entire mode is broken
4981                                 }
4982                         }
4983                 }
4984                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4985                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4986         }
4987         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4988         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4989         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4990 }
4991 #endif
4992
4993 void R_GLSL_Restart_f(void)
4994 {
4995         unsigned int i, limit;
4996         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4997                 Mem_Free(glslshaderstring);
4998         glslshaderstring = NULL;
4999         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5000                 Mem_Free(cgshaderstring);
5001         cgshaderstring = NULL;
5002         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5003                 Mem_Free(hlslshaderstring);
5004         hlslshaderstring = NULL;
5005         switch(vid.renderpath)
5006         {
5007         case RENDERPATH_D3D9:
5008 #ifdef SUPPORTD3D
5009                 {
5010                         r_hlsl_permutation_t *p;
5011                         r_hlsl_permutation = NULL;
5012 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5014 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5016                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5017                         for (i = 0;i < limit;i++)
5018                         {
5019                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5020                                 {
5021                                         if (p->vertexshader)
5022                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5023                                         if (p->pixelshader)
5024                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5025                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5026                                 }
5027                         }
5028                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5029                 }
5030 #endif
5031                 break;
5032         case RENDERPATH_D3D10:
5033                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5034                 break;
5035         case RENDERPATH_D3D11:
5036                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5037                 break;
5038         case RENDERPATH_GL20:
5039                 {
5040                         r_glsl_permutation_t *p;
5041                         r_glsl_permutation = NULL;
5042                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5043                         for (i = 0;i < limit;i++)
5044                         {
5045                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5046                                 {
5047                                         GL_Backend_FreeProgram(p->program);
5048                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5049                                 }
5050                         }
5051                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5052                 }
5053                 break;
5054         case RENDERPATH_CGGL:
5055 #ifdef SUPPORTCG
5056                 {
5057                         r_cg_permutation_t *p;
5058                         r_cg_permutation = NULL;
5059                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5060                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5061                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5062                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5063                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5064                         for (i = 0;i < limit;i++)
5065                         {
5066                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5067                                 {
5068                                         if (p->vprogram)
5069                                                 cgDestroyProgram(p->vprogram);
5070                                         if (p->fprogram)
5071                                                 cgDestroyProgram(p->fprogram);
5072                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5073                                 }
5074                         }
5075                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5076                 }
5077 #endif
5078                 break;
5079         case RENDERPATH_GL13:
5080         case RENDERPATH_GL11:
5081                 break;
5082         }
5083 }
5084
5085 void R_GLSL_DumpShader_f(void)
5086 {
5087         int i;
5088         qfile_t *file;
5089
5090         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5091         if (file)
5092         {
5093                 FS_Print(file, "/* The engine may define the following macros:\n");
5094                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5095                 for (i = 0;i < SHADERMODE_COUNT;i++)
5096                         FS_Print(file, glslshadermodeinfo[i].pretext);
5097                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5098                         FS_Print(file, shaderpermutationinfo[i].pretext);
5099                 FS_Print(file, "*/\n");
5100                 FS_Print(file, builtinshaderstring);
5101                 FS_Close(file);
5102                 Con_Printf("glsl/default.glsl written\n");
5103         }
5104         else
5105                 Con_Printf("failed to write to glsl/default.glsl\n");
5106
5107 #ifdef SUPPORTCG
5108         file = FS_OpenRealFile("cg/default.cg", "w", false);
5109         if (file)
5110         {
5111                 FS_Print(file, "/* The engine may define the following macros:\n");
5112                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5113                 for (i = 0;i < SHADERMODE_COUNT;i++)
5114                         FS_Print(file, cgshadermodeinfo[i].pretext);
5115                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5116                         FS_Print(file, shaderpermutationinfo[i].pretext);
5117                 FS_Print(file, "*/\n");
5118                 FS_Print(file, builtincgshaderstring);
5119                 FS_Close(file);
5120                 Con_Printf("cg/default.cg written\n");
5121         }
5122         else
5123                 Con_Printf("failed to write to cg/default.cg\n");
5124 #endif
5125
5126 #ifdef SUPPORTD3D
5127         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5128         if (file)
5129         {
5130                 FS_Print(file, "/* The engine may define the following macros:\n");
5131                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5132                 for (i = 0;i < SHADERMODE_COUNT;i++)
5133                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5134                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5135                         FS_Print(file, shaderpermutationinfo[i].pretext);
5136                 FS_Print(file, "*/\n");
5137                 FS_Print(file, builtincgshaderstring);
5138                 FS_Close(file);
5139                 Con_Printf("hlsl/default.hlsl written\n");
5140         }
5141         else
5142                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5143 #endif
5144 }
5145
5146 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5147 {
5148         if (!second)
5149                 texturemode = GL_MODULATE;
5150         switch (vid.renderpath)
5151         {
5152         case RENDERPATH_D3D9:
5153 #ifdef SUPPORTD3D
5154                 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))));
5155                 R_Mesh_TexBind(GL20TU_FIRST , first );
5156                 R_Mesh_TexBind(GL20TU_SECOND, second);
5157 #endif
5158                 break;
5159         case RENDERPATH_D3D10:
5160                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5161                 break;
5162         case RENDERPATH_D3D11:
5163                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5164                 break;
5165         case RENDERPATH_GL20:
5166                 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))));
5167                 R_Mesh_TexBind(GL20TU_FIRST , first );
5168                 R_Mesh_TexBind(GL20TU_SECOND, second);
5169                 break;
5170         case RENDERPATH_CGGL:
5171 #ifdef SUPPORTCG
5172                 CHECKCGERROR
5173                 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))));
5174                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5175                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5176 #endif
5177                 break;
5178         case RENDERPATH_GL13:
5179                 R_Mesh_TexBind(0, first );
5180                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5181                 R_Mesh_TexBind(1, second);
5182                 if (second)
5183                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5184                 break;
5185         case RENDERPATH_GL11:
5186                 R_Mesh_TexBind(0, first );
5187                 break;
5188         }
5189 }
5190
5191 void R_SetupShader_DepthOrShadow(void)
5192 {
5193         switch (vid.renderpath)
5194         {
5195         case RENDERPATH_D3D9:
5196 #ifdef SUPPORTD3D
5197                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5198 #endif
5199                 break;
5200         case RENDERPATH_D3D10:
5201                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5202                 break;
5203         case RENDERPATH_D3D11:
5204                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5205                 break;
5206         case RENDERPATH_GL20:
5207                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5208                 break;
5209         case RENDERPATH_CGGL:
5210 #ifdef SUPPORTCG
5211                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5212 #endif
5213                 break;
5214         case RENDERPATH_GL13:
5215                 R_Mesh_TexBind(0, 0);
5216                 R_Mesh_TexBind(1, 0);
5217                 break;
5218         case RENDERPATH_GL11:
5219                 R_Mesh_TexBind(0, 0);
5220                 break;
5221         }
5222 }
5223
5224 void R_SetupShader_ShowDepth(void)
5225 {
5226         switch (vid.renderpath)
5227         {
5228         case RENDERPATH_D3D9:
5229 #ifdef SUPPORTHLSL
5230                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5231 #endif
5232                 break;
5233         case RENDERPATH_D3D10:
5234                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5235                 break;
5236         case RENDERPATH_D3D11:
5237                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5238                 break;
5239         case RENDERPATH_GL20:
5240                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5241                 break;
5242         case RENDERPATH_CGGL:
5243 #ifdef SUPPORTCG
5244                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5245 #endif
5246                 break;
5247         case RENDERPATH_GL13:
5248                 break;
5249         case RENDERPATH_GL11:
5250                 break;
5251         }
5252 }
5253
5254 extern qboolean r_shadow_usingdeferredprepass;
5255 extern cvar_t r_shadow_deferred_8bitrange;
5256 extern rtexture_t *r_shadow_attenuationgradienttexture;
5257 extern rtexture_t *r_shadow_attenuation2dtexture;
5258 extern rtexture_t *r_shadow_attenuation3dtexture;
5259 extern qboolean r_shadow_usingshadowmap2d;
5260 extern qboolean r_shadow_usingshadowmaportho;
5261 extern float r_shadow_shadowmap_texturescale[2];
5262 extern float r_shadow_shadowmap_parameters[4];
5263 extern qboolean r_shadow_shadowmapvsdct;
5264 extern qboolean r_shadow_shadowmapsampler;
5265 extern int r_shadow_shadowmappcf;
5266 extern rtexture_t *r_shadow_shadowmap2dtexture;
5267 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5268 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5269 extern matrix4x4_t r_shadow_shadowmapmatrix;
5270 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5271 extern int r_shadow_prepass_width;
5272 extern int r_shadow_prepass_height;
5273 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5274 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5275 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5276 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5277 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5278 extern cvar_t gl_mesh_separatearrays;
5279 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5280 {
5281         // a blendfunc allows colormod if:
5282         // a) it can never keep the destination pixel invariant, or
5283         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5284         // this is to prevent unintended side effects from colormod
5285
5286         // in formulas:
5287         // IF there is a (s, sa) for which for all (d, da),
5288         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5289         // THEN, for this (s, sa) and all (colormod, d, da):
5290         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5291         // OBVIOUSLY, this means that
5292         //   s*colormod * src(s*colormod, d, sa, da) = 0
5293         //   dst(s*colormod, d, sa, da)              = 1
5294
5295         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5296
5297         // main condition to leave dst color invariant:
5298         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5299         //   src == GL_ZERO:
5300         //     s * 0 + d * dst(s, d, sa, da) == d
5301         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is a problem for GL_SRC_COLOR only
5303         //   src == GL_ONE:
5304         //     s + d * dst(s, d, sa, da) == d
5305         //       => s == 0
5306         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod is never problematic for these
5308         //   src == GL_SRC_COLOR:
5309         //     s*s + d * dst(s, d, sa, da) == d
5310         //       => s == 0
5311         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312         //       => colormod is never problematic for these
5313         //   src == GL_ONE_MINUS_SRC_COLOR:
5314         //     s*(1-s) + d * dst(s, d, sa, da) == d
5315         //       => s == 0 or s == 1
5316         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5317         //       => colormod is a problem for GL_SRC_COLOR only
5318         //   src == GL_DST_COLOR
5319         //     s*d + d * dst(s, d, sa, da) == d
5320         //       => s == 1
5321         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5322         //       => colormod is always a problem
5323         //     or
5324         //       => s == 0
5325         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5326         //       => colormod is never problematic for these
5327         //       => BUT, we do not know s! We must assume it is problematic
5328         //       then... except in GL_ONE case, where we know all invariant
5329         //       cases are fine
5330         //   src == GL_ONE_MINUS_DST_COLOR
5331         //     s*(1-d) + d * dst(s, d, sa, da) == d
5332         //       => s == 0 (1-d is impossible to handle for our desired result)
5333         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334         //       => colormod is never problematic for these
5335         //   src == GL_SRC_ALPHA
5336         //     s*sa + d * dst(s, d, sa, da) == d
5337         //       => s == 0, or sa == 0
5338         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5339         //       => colormod breaks in the case GL_SRC_COLOR only
5340         //   src == GL_ONE_MINUS_SRC_ALPHA
5341         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5342         //       => s == 0, or sa == 1
5343         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5344         //       => colormod breaks in the case GL_SRC_COLOR only
5345         //   src == GL_DST_ALPHA
5346         //     s*da + d * dst(s, d, sa, da) == d
5347         //       => s == 0
5348         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5349         //       => colormod is never problematic for these
5350
5351         switch(src)
5352         {
5353                 case GL_ZERO:
5354                 case GL_ONE_MINUS_SRC_COLOR:
5355                 case GL_SRC_ALPHA:
5356                 case GL_ONE_MINUS_SRC_ALPHA:
5357                         if(dst == GL_SRC_COLOR)
5358                                 return false;
5359                         return true;
5360                 case GL_ONE:
5361                 case GL_SRC_COLOR:
5362                 case GL_ONE_MINUS_DST_COLOR:
5363                 case GL_DST_ALPHA:
5364                 case GL_ONE_MINUS_DST_ALPHA:
5365                         return true;
5366                 case GL_DST_COLOR:
5367                         if(dst == GL_ONE)
5368                                 return true;
5369                         return false;
5370                 default:
5371                         return false;
5372         }
5373 }
5374 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)
5375 {
5376         // select a permutation of the lighting shader appropriate to this
5377         // combination of texture, entity, light source, and fogging, only use the
5378         // minimum features necessary to avoid wasting rendering time in the
5379         // fragment shader on features that are not being used
5380         unsigned int permutation = 0;
5381         unsigned int mode = 0;
5382         qboolean allow_colormod;
5383         static float dummy_colormod[3] = {1, 1, 1};
5384         float *colormod = rsurface.colormod;
5385         float m16f[16];
5386         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5387         if (rsurfacepass == RSURFPASS_BACKGROUND)
5388         {
5389                 // distorted background
5390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5391                 {
5392                         mode = SHADERMODE_WATER;
5393                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5394                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5395                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5396                         {
5397                                 // this is the right thing to do for wateralpha
5398                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5399                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5400                         }
5401                         else
5402                         {
5403                                 // this is the right thing to do for entity alpha
5404                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5405                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5406                         }
5407                 }
5408                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5409                 {
5410                         mode = SHADERMODE_REFRACTION;
5411                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5412                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5413                 }
5414                 else
5415                 {
5416                         mode = SHADERMODE_GENERIC;
5417                         permutation |= SHADERPERMUTATION_DIFFUSE;
5418                         GL_BlendFunc(GL_ONE, GL_ZERO);
5419                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5420                 }
5421                 GL_AlphaTest(false);
5422         }
5423         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5424         {
5425                 if (r_glsl_offsetmapping.integer)
5426                 {
5427                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5428                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5429                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5430                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5431                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5432                         {
5433                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5434                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5435                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436                         }
5437                 }
5438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5439                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5441                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5442                 // normalmap (deferred prepass), may use alpha test on diffuse
5443                 mode = SHADERMODE_DEFERREDGEOMETRY;
5444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5446                 GL_AlphaTest(false);
5447                 GL_BlendFunc(GL_ONE, GL_ZERO);
5448                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5449         }
5450         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5451         {
5452                 if (r_glsl_offsetmapping.integer)
5453                 {
5454                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5456                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5457                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5458                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5459                         {
5460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5461                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5462                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5463                         }
5464                 }
5465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467                 // light source
5468                 mode = SHADERMODE_LIGHTSOURCE;
5469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5470                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5471                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5472                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5473                 if (diffusescale > 0)
5474                         permutation |= SHADERPERMUTATION_DIFFUSE;
5475                 if (specularscale > 0)
5476                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5477                 if (r_refdef.fogenabled)
5478                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5479                 if (rsurface.texture->colormapping)
5480                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5481                 if (r_shadow_usingshadowmap2d)
5482                 {
5483                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5484                         if(r_shadow_shadowmapvsdct)
5485                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5486
5487                         if (r_shadow_shadowmapsampler)
5488                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5489                         if (r_shadow_shadowmappcf > 1)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5491                         else if (r_shadow_shadowmappcf)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5493                 }
5494                 if (rsurface.texture->reflectmasktexture)
5495                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5496                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5497                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5498                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5499         }
5500         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5501         {
5502                 if (r_glsl_offsetmapping.integer)
5503                 {
5504                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5505                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5506                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5507                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5508                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5509                         {
5510                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5511                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5512                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5513                         }
5514                 }
5515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5516                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5517                 // unshaded geometry (fullbright or ambient model lighting)
5518                 mode = SHADERMODE_FLATCOLOR;
5519                 ambientscale = diffusescale = specularscale = 0;
5520                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5521                         permutation |= SHADERPERMUTATION_GLOW;
5522                 if (r_refdef.fogenabled)
5523                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5524                 if (rsurface.texture->colormapping)
5525                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5526                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5527                 {
5528                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5529                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5530
5531                         if (r_shadow_shadowmapsampler)
5532                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5533                         if (r_shadow_shadowmappcf > 1)
5534                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5535                         else if (r_shadow_shadowmappcf)
5536                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5537                 }
5538                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5539                         permutation |= SHADERPERMUTATION_REFLECTION;
5540                 if (rsurface.texture->reflectmasktexture)
5541                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5542                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5543                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5544                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5545         }
5546         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5547         {
5548                 if (r_glsl_offsetmapping.integer)
5549                 {
5550                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5551                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5552                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5553                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5554                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5555                         {
5556                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5557                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5558                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5559                         }
5560                 }
5561                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5562                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5563                 // directional model lighting
5564                 mode = SHADERMODE_LIGHTDIRECTION;
5565                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5566                         permutation |= SHADERPERMUTATION_GLOW;
5567                 permutation |= SHADERPERMUTATION_DIFFUSE;
5568                 if (specularscale > 0)
5569                         permutation |= SHADERPERMUTATION_SPECULAR;
5570                 if (r_refdef.fogenabled)
5571                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5572                 if (rsurface.texture->colormapping)
5573                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5574                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5575                 {
5576                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5577                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5578
5579                         if (r_shadow_shadowmapsampler)
5580                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5581                         if (r_shadow_shadowmappcf > 1)
5582                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5583                         else if (r_shadow_shadowmappcf)
5584                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5585                 }
5586                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5587                         permutation |= SHADERPERMUTATION_REFLECTION;
5588                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5589                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5590                 if (rsurface.texture->reflectmasktexture)
5591                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5592                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5593                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5594                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5595         }
5596         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5597         {
5598                 if (r_glsl_offsetmapping.integer)
5599                 {
5600                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5601                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5602                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5603                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5604                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5605                         {
5606                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5607                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5608                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5609                         }
5610                 }
5611                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5612                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5613                 // ambient model lighting
5614                 mode = SHADERMODE_LIGHTDIRECTION;
5615                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5616                         permutation |= SHADERPERMUTATION_GLOW;
5617                 if (r_refdef.fogenabled)
5618                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5619                 if (rsurface.texture->colormapping)
5620                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5621                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5622                 {
5623                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5624                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5625
5626                         if (r_shadow_shadowmapsampler)
5627                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5628                         if (r_shadow_shadowmappcf > 1)
5629                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5630                         else if (r_shadow_shadowmappcf)
5631                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5632                 }
5633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5634                         permutation |= SHADERPERMUTATION_REFLECTION;
5635                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5636                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5637                 if (rsurface.texture->reflectmasktexture)
5638                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5639                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5640                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5641                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5642         }
5643         else
5644         {
5645                 if (r_glsl_offsetmapping.integer)
5646                 {
5647                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5648                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5649                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5650                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5651                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5652                         {
5653                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5654                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5655                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5656                         }
5657                 }
5658                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5659                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5660                 // lightmapped wall
5661                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5662                         permutation |= SHADERPERMUTATION_GLOW;
5663                 if (r_refdef.fogenabled)
5664                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5665                 if (rsurface.texture->colormapping)
5666                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5667                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5668                 {
5669                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5670                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5671
5672                         if (r_shadow_shadowmapsampler)
5673                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5674                         if (r_shadow_shadowmappcf > 1)
5675                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5676                         else if (r_shadow_shadowmappcf)
5677                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5678                 }
5679                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5680                         permutation |= SHADERPERMUTATION_REFLECTION;
5681                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5682                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5683                 if (rsurface.texture->reflectmasktexture)
5684                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5685                 if (FAKELIGHT_ENABLED)
5686                 {
5687                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5688                         mode = SHADERMODE_FAKELIGHT;
5689                         permutation |= SHADERPERMUTATION_DIFFUSE;
5690                         if (specularscale > 0)
5691                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5692                 }
5693                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5694                 {
5695                         // deluxemapping (light direction texture)
5696                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5697                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5698                         else
5699                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5700                         permutation |= SHADERPERMUTATION_DIFFUSE;
5701                         if (specularscale > 0)
5702                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5703                 }
5704                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5705                 {
5706                         // fake deluxemapping (uniform light direction in tangentspace)
5707                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5708                         permutation |= SHADERPERMUTATION_DIFFUSE;
5709                         if (specularscale > 0)
5710                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5711                 }
5712                 else if (rsurface.uselightmaptexture)
5713                 {
5714                         // ordinary lightmapping (q1bsp, q3bsp)
5715                         mode = SHADERMODE_LIGHTMAP;
5716                 }
5717                 else
5718                 {
5719                         // ordinary vertex coloring (q3bsp)
5720                         mode = SHADERMODE_VERTEXCOLOR;
5721                 }
5722                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5723                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5724                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5725         }
5726         if(!allow_colormod)
5727                 colormod = dummy_colormod;
5728         switch(vid.renderpath)
5729         {
5730         case RENDERPATH_D3D9:
5731 #ifdef SUPPORTD3D
5732                 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);
5733                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5734                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5735                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5736                 if (mode == SHADERMODE_LIGHTSOURCE)
5737                 {
5738                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5739                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5740                 }
5741                 else
5742                 {
5743                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5744                         {
5745                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5746                         }
5747                 }
5748                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5749                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5750                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5751                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5752                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5753
5754                 if (mode == SHADERMODE_LIGHTSOURCE)
5755                 {
5756                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5757                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5758                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5759                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5760                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5761
5762                         // additive passes are only darkened by fog, not tinted
5763                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5764                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5765                 }
5766                 else
5767                 {
5768                         if (mode == SHADERMODE_FLATCOLOR)
5769                         {
5770                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5771                         }
5772                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5773                         {
5774                                 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]);
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5776                                 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);
5777                                 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);
5778                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5779                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5780                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5781                         }
5782                         else
5783                         {
5784                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5785                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5786                                 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);
5787                                 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);
5788                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5789                         }
5790                         // additive passes are only darkened by fog, not tinted
5791                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5792                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5793                         else
5794                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5795                         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);
5796                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5797                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5798                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5799                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5800                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5801                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5802                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5803                         if (mode == SHADERMODE_WATER)
5804                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5805                 }
5806                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5807                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5808                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5809                 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));
5810                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5811                 if (rsurface.texture->pantstexture)
5812                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5813                 else
5814                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5815                 if (rsurface.texture->shirttexture)
5816                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5817                 else
5818                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5819                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5820                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5821                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5822                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5823                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5824                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5825                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5826
5827                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5828                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5829                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5830                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5831                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5832                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5833                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5834                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5835                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5836                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5837                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5838                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5839                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5840                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5841                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5842                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5843                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5844                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5845                 {
5846                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5847                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5848                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5849                 }
5850                 else
5851                 {
5852                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5853                 }
5854 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5855 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5856                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5857                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5858                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5859                 {
5860                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5861                         if (rsurface.rtlight)
5862                         {
5863                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5864                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5865                         }
5866                 }
5867 #endif
5868                 break;
5869         case RENDERPATH_D3D10:
5870                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5871                 break;
5872         case RENDERPATH_D3D11:
5873                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5874                 break;
5875         case RENDERPATH_GL20:
5876                 if (gl_mesh_separatearrays.integer)
5877                 {
5878                         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);
5879                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5880                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5881                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5882                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5883                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5884                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5885                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5886                 }
5887                 else
5888                 {
5889                         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);
5890                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5891                 }
5892                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5893                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5894                 if (mode == SHADERMODE_LIGHTSOURCE)
5895                 {
5896                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5897                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5898                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5899                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5900                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5901                         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);
5902         
5903                         // additive passes are only darkened by fog, not tinted
5904                         if (r_glsl_permutation->loc_FogColor >= 0)
5905                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5906                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5907                 }
5908                 else
5909                 {
5910                         if (mode == SHADERMODE_FLATCOLOR)
5911                         {
5912                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5913                         }
5914                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5915                         {
5916                                 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]);
5917                                 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]);
5918                                 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);
5919                                 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);
5920                                 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);
5921                                 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]);
5922                                 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]);
5923                         }
5924                         else
5925                         {
5926                                 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]);
5927                                 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]);
5928                                 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);
5929                                 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);
5930                                 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);
5931                         }
5932                         // additive passes are only darkened by fog, not tinted
5933                         if (r_glsl_permutation->loc_FogColor >= 0)
5934                         {
5935                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5936                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5937                                 else
5938                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5939                         }
5940                         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);
5941                         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]);
5942                         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]);
5943                         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]);
5944                         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]);
5945                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5946                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5947                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5948                         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]);
5949                 }
5950                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5951                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5952                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5953                 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]);
5954                 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]);
5955
5956                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5957                 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));
5958                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5959                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5960                 {
5961                         if (rsurface.texture->pantstexture)
5962                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5963                         else
5964                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5965                 }
5966                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5967                 {
5968                         if (rsurface.texture->shirttexture)
5969                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5970                         else
5971                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5972                 }
5973                 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]);
5974                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5975                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5976                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5977                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5978                 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]);
5979                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5980
5981         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5982         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5983         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5984                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5985                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5986                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5987                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5988                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5989                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5990                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5991                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5992                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5993                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5994                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5995                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5996                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5997                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5998                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5999                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6000                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6001                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6002                 {
6003                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6004                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6005                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6006                 }
6007                 else
6008                 {
6009                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6010                 }
6011 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6012 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6013                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6014                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6015                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6016                 {
6017                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6018                         if (rsurface.rtlight)
6019                         {
6020                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6021                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6022                         }
6023                 }
6024                 CHECKGLERROR
6025                 break;
6026         case RENDERPATH_CGGL:
6027 #ifdef SUPPORTCG
6028                 if (gl_mesh_separatearrays.integer)
6029                 {
6030                         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);
6031                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6032                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6033                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6034                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6035                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6036                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6037                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6038                 }
6039                 else
6040                 {
6041                         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);
6042                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6043                 }
6044                 R_SetupShader_SetPermutationCG(mode, permutation);
6045                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6046                 if (mode == SHADERMODE_LIGHTSOURCE)
6047                 {
6048                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6049                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6050                 }
6051                 else
6052                 {
6053                         if (mode == SHADERMODE_LIGHTDIRECTION)
6054                         {
6055                                 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
6056                         }
6057                 }
6058                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6059                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6060                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6061                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6062                 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
6063                 CHECKGLERROR
6064
6065                 if (mode == SHADERMODE_LIGHTSOURCE)
6066                 {
6067                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6068                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6069                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6070                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6071                         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
6072
6073                         // additive passes are only darkened by fog, not tinted
6074                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6075                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6076                 }
6077                 else
6078                 {
6079                         if (mode == SHADERMODE_FLATCOLOR)
6080                         {
6081                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6082                         }
6083                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6084                         {
6085                                 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
6086                                 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
6087                                 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
6088                                 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
6089                                 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
6090                                 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
6091                                 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
6092                         }
6093                         else
6094                         {
6095                                 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
6096                                 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
6097                                 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
6098                                 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
6099                                 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
6100                         }
6101                         // additive passes are only darkened by fog, not tinted
6102                         if (r_cg_permutation->fp_FogColor)
6103                         {
6104                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6105                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6106                                 else
6107                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6108                                 CHECKCGERROR
6109                         }
6110                         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
6111                         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
6112                         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
6113                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4f(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
6114                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4f(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
6115                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6116                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6117                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6118                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6119                 }
6120                 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
6121                 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
6122                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6123                 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
6124                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6125                 if (r_cg_permutation->fp_Color_Pants)
6126                 {
6127                         if (rsurface.texture->pantstexture)
6128                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6129                         else
6130                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6131                         CHECKCGERROR
6132                 }
6133                 if (r_cg_permutation->fp_Color_Shirt)
6134                 {
6135                         if (rsurface.texture->shirttexture)
6136                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6137                         else
6138                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6139                         CHECKCGERROR
6140                 }
6141                 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
6142                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6143                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6144                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6145                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6146                 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
6147                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6148
6149         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6150         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6151         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6152                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6153                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6158                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6159                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6161                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6162                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6163                 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
6164                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6165                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6166                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6167                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6168                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6169                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6170                 {
6171                         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
6172                         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
6173                         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
6174                 }
6175                 else
6176                 {
6177                         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
6178                 }
6179                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6180                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6181                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6182                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6183                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6184                 {
6185                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6186                         if (rsurface.rtlight)
6187                         {
6188                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6189                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6190                         }
6191                 }
6192
6193                 CHECKGLERROR
6194 #endif
6195                 break;
6196         case RENDERPATH_GL13:
6197         case RENDERPATH_GL11:
6198                 break;
6199         }
6200 }
6201
6202 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6203 {
6204         // select a permutation of the lighting shader appropriate to this
6205         // combination of texture, entity, light source, and fogging, only use the
6206         // minimum features necessary to avoid wasting rendering time in the
6207         // fragment shader on features that are not being used
6208         unsigned int permutation = 0;
6209         unsigned int mode = 0;
6210         const float *lightcolorbase = rtlight->currentcolor;
6211         float ambientscale = rtlight->ambientscale;
6212         float diffusescale = rtlight->diffusescale;
6213         float specularscale = rtlight->specularscale;
6214         // this is the location of the light in view space
6215         vec3_t viewlightorigin;
6216         // this transforms from view space (camera) to light space (cubemap)
6217         matrix4x4_t viewtolight;
6218         matrix4x4_t lighttoview;
6219         float viewtolight16f[16];
6220         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6221         // light source
6222         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6223         if (rtlight->currentcubemap != r_texture_whitecube)
6224                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6225         if (diffusescale > 0)
6226                 permutation |= SHADERPERMUTATION_DIFFUSE;
6227         if (specularscale > 0)
6228                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6229         if (r_shadow_usingshadowmap2d)
6230         {
6231                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6232                 if (r_shadow_shadowmapvsdct)
6233                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6234
6235                 if (r_shadow_shadowmapsampler)
6236                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6237                 if (r_shadow_shadowmappcf > 1)
6238                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6239                 else if (r_shadow_shadowmappcf)
6240                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6241         }
6242         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6243         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6244         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6245         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6246         switch(vid.renderpath)
6247         {
6248         case RENDERPATH_D3D9:
6249 #ifdef SUPPORTD3D
6250                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6251                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6252                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6253                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6254                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6255                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6256                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6257                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6258                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6259                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6260                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6261
6262                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6263                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6264                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6265                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6266                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6267                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6268 #endif
6269                 break;
6270         case RENDERPATH_D3D10:
6271                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6272                 break;
6273         case RENDERPATH_D3D11:
6274                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6275                 break;
6276         case RENDERPATH_GL20:
6277                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6278                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6279                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6280                 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);
6281                 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);
6282                 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);
6283                 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]);
6284                 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]);
6285                 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));
6286                 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]);
6287                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6288
6289                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6290                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6291                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6292                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6293                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6294                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6295                 break;
6296         case RENDERPATH_CGGL:
6297 #ifdef SUPPORTCG
6298                 R_SetupShader_SetPermutationCG(mode, permutation);
6299                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6300                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6301                 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
6302                 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
6303                 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
6304                 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
6305                 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
6306                 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
6307                 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
6308                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6309
6310                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6311                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6312                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6313                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6314                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6315                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6316 #endif
6317                 break;
6318         case RENDERPATH_GL13:
6319         case RENDERPATH_GL11:
6320                 break;
6321         }
6322 }
6323
6324 #define SKINFRAME_HASH 1024
6325
6326 typedef struct
6327 {
6328         int loadsequence; // incremented each level change
6329         memexpandablearray_t array;
6330         skinframe_t *hash[SKINFRAME_HASH];
6331 }
6332 r_skinframe_t;
6333 r_skinframe_t r_skinframe;
6334
6335 void R_SkinFrame_PrepareForPurge(void)
6336 {
6337         r_skinframe.loadsequence++;
6338         // wrap it without hitting zero
6339         if (r_skinframe.loadsequence >= 200)
6340                 r_skinframe.loadsequence = 1;
6341 }
6342
6343 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6344 {
6345         if (!skinframe)
6346                 return;
6347         // mark the skinframe as used for the purging code
6348         skinframe->loadsequence = r_skinframe.loadsequence;
6349 }
6350
6351 void R_SkinFrame_Purge(void)
6352 {
6353         int i;
6354         skinframe_t *s;
6355         for (i = 0;i < SKINFRAME_HASH;i++)
6356         {
6357                 for (s = r_skinframe.hash[i];s;s = s->next)
6358                 {
6359                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6360                         {
6361                                 if (s->merged == s->base)
6362                                         s->merged = NULL;
6363                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6364                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6365                                 R_PurgeTexture(s->merged);s->merged = NULL;
6366                                 R_PurgeTexture(s->base  );s->base   = NULL;
6367                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6368                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6369                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6370                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6371                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6372                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6373                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6374                                 s->loadsequence = 0;
6375                         }
6376                 }
6377         }
6378 }
6379
6380 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6381         skinframe_t *item;
6382         char basename[MAX_QPATH];
6383
6384         Image_StripImageExtension(name, basename, sizeof(basename));
6385
6386         if( last == NULL ) {
6387                 int hashindex;
6388                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6389                 item = r_skinframe.hash[hashindex];
6390         } else {
6391                 item = last->next;
6392         }
6393
6394         // linearly search through the hash bucket
6395         for( ; item ; item = item->next ) {
6396                 if( !strcmp( item->basename, basename ) ) {
6397                         return item;
6398                 }
6399         }
6400         return NULL;
6401 }
6402
6403 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6404 {
6405         skinframe_t *item;
6406         int hashindex;
6407         char basename[MAX_QPATH];
6408
6409         Image_StripImageExtension(name, basename, sizeof(basename));
6410
6411         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6412         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6413                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6414                         break;
6415
6416         if (!item) {
6417                 rtexture_t *dyntexture;
6418                 // check whether its a dynamic texture
6419                 dyntexture = CL_GetDynTexture( basename );
6420                 if (!add && !dyntexture)
6421                         return NULL;
6422                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6423                 memset(item, 0, sizeof(*item));
6424                 strlcpy(item->basename, basename, sizeof(item->basename));
6425                 item->base = dyntexture; // either NULL or dyntexture handle
6426                 item->textureflags = textureflags;
6427                 item->comparewidth = comparewidth;
6428                 item->compareheight = compareheight;
6429                 item->comparecrc = comparecrc;
6430                 item->next = r_skinframe.hash[hashindex];
6431                 r_skinframe.hash[hashindex] = item;
6432         }
6433         else if( item->base == NULL )
6434         {
6435                 rtexture_t *dyntexture;
6436                 // check whether its a dynamic texture
6437                 // 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]
6438                 dyntexture = CL_GetDynTexture( basename );
6439                 item->base = dyntexture; // either NULL or dyntexture handle
6440         }
6441
6442         R_SkinFrame_MarkUsed(item);
6443         return item;
6444 }
6445
6446 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6447         { \
6448                 unsigned long long avgcolor[5], wsum; \
6449                 int pix, comp, w; \
6450                 avgcolor[0] = 0; \
6451                 avgcolor[1] = 0; \
6452                 avgcolor[2] = 0; \
6453                 avgcolor[3] = 0; \
6454                 avgcolor[4] = 0; \
6455                 wsum = 0; \
6456                 for(pix = 0; pix < cnt; ++pix) \
6457                 { \
6458                         w = 0; \
6459                         for(comp = 0; comp < 3; ++comp) \
6460                                 w += getpixel; \
6461                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6462                         { \
6463                                 ++wsum; \
6464                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6465                                 w = getpixel; \
6466                                 for(comp = 0; comp < 3; ++comp) \
6467                                         avgcolor[comp] += getpixel * w; \
6468                                 avgcolor[3] += w; \
6469                         } \
6470                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6471                         avgcolor[4] += getpixel; \
6472                 } \
6473                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6474                         avgcolor[3] = 1; \
6475                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6476                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6477                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6478                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6479         }
6480
6481 extern cvar_t gl_picmip;
6482 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6483 {
6484         int j;
6485         unsigned char *pixels;
6486         unsigned char *bumppixels;
6487         unsigned char *basepixels = NULL;
6488         int basepixels_width = 0;
6489         int basepixels_height = 0;
6490         skinframe_t *skinframe;
6491         rtexture_t *ddsbase = NULL;
6492         qboolean ddshasalpha = false;
6493         float ddsavgcolor[4];
6494         char basename[MAX_QPATH];
6495         int miplevel = R_PicmipForFlags(textureflags);
6496         int savemiplevel = miplevel;
6497         int mymiplevel;
6498
6499         if (cls.state == ca_dedicated)
6500                 return NULL;
6501
6502         // return an existing skinframe if already loaded
6503         // if loading of the first image fails, don't make a new skinframe as it
6504         // would cause all future lookups of this to be missing
6505         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6506         if (skinframe && skinframe->base)
6507                 return skinframe;
6508
6509         Image_StripImageExtension(name, basename, sizeof(basename));
6510
6511         // check for DDS texture file first
6512         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6513         {
6514                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6515                 if (basepixels == NULL)
6516                         return NULL;
6517         }
6518
6519         // FIXME handle miplevel
6520
6521         if (developer_loading.integer)
6522                 Con_Printf("loading skin \"%s\"\n", name);
6523
6524         // we've got some pixels to store, so really allocate this new texture now
6525         if (!skinframe)
6526                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6527         skinframe->stain = NULL;
6528         skinframe->merged = NULL;
6529         skinframe->base = NULL;
6530         skinframe->pants = NULL;
6531         skinframe->shirt = NULL;
6532         skinframe->nmap = NULL;
6533         skinframe->gloss = NULL;
6534         skinframe->glow = NULL;
6535         skinframe->fog = NULL;
6536         skinframe->reflect = NULL;
6537         skinframe->hasalpha = false;
6538
6539         if (ddsbase)
6540         {
6541                 skinframe->base = ddsbase;
6542                 skinframe->hasalpha = ddshasalpha;
6543                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6544                 if (r_loadfog && skinframe->hasalpha)
6545                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6546                 //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]);
6547         }
6548         else
6549         {
6550                 basepixels_width = image_width;
6551                 basepixels_height = image_height;
6552                 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);
6553                 if (textureflags & TEXF_ALPHA)
6554                 {
6555                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6556                         {
6557                                 if (basepixels[j] < 255)
6558                                 {
6559                                         skinframe->hasalpha = true;
6560                                         break;
6561                                 }
6562                         }
6563                         if (r_loadfog && skinframe->hasalpha)
6564                         {
6565                                 // has transparent pixels
6566                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6567                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6568                                 {
6569                                         pixels[j+0] = 255;
6570                                         pixels[j+1] = 255;
6571                                         pixels[j+2] = 255;
6572                                         pixels[j+3] = basepixels[j+3];
6573                                 }
6574                                 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);
6575                                 Mem_Free(pixels);
6576                         }
6577                 }
6578                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6579                 //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]);
6580                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6581                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6582                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6583                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6584         }
6585
6586         if (r_loaddds)
6587         {
6588                 mymiplevel = savemiplevel;
6589                 if (r_loadnormalmap)
6590                         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);
6591                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6592                 if (r_loadgloss)
6593                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6594                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6595                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6596                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6597         }
6598
6599         // _norm is the name used by tenebrae and has been adopted as standard
6600         if (r_loadnormalmap && skinframe->nmap == NULL)
6601         {
6602                 mymiplevel = savemiplevel;
6603                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6604                 {
6605                         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);
6606                         Mem_Free(pixels);
6607                         pixels = NULL;
6608                 }
6609                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6610                 {
6611                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6612                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6613                         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);
6614                         Mem_Free(pixels);
6615                         Mem_Free(bumppixels);
6616                 }
6617                 else if (r_shadow_bumpscale_basetexture.value > 0)
6618                 {
6619                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6620                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6621                         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);
6622                         Mem_Free(pixels);
6623                 }
6624                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6625                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6626         }
6627
6628         // _luma is supported only for tenebrae compatibility
6629         // _glow is the preferred name
6630         mymiplevel = savemiplevel;
6631         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))))
6632         {
6633                 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);
6634                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6635                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6636                 Mem_Free(pixels);pixels = NULL;
6637         }
6638
6639         mymiplevel = savemiplevel;
6640         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641         {
6642                 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);
6643                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6644                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6645                 Mem_Free(pixels);
6646                 pixels = NULL;
6647         }
6648
6649         mymiplevel = savemiplevel;
6650         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651         {
6652                 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);
6653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6654                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6655                 Mem_Free(pixels);
6656                 pixels = NULL;
6657         }
6658
6659         mymiplevel = savemiplevel;
6660         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6661         {
6662                 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);
6663                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6664                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6665                 Mem_Free(pixels);
6666                 pixels = NULL;
6667         }
6668
6669         mymiplevel = savemiplevel;
6670         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6671         {
6672                 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);
6673                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6674                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6675                 Mem_Free(pixels);
6676                 pixels = NULL;
6677         }
6678
6679         if (basepixels)
6680                 Mem_Free(basepixels);
6681
6682         return skinframe;
6683 }
6684
6685 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6686 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6687 {
6688         int i;
6689         unsigned char *temp1, *temp2;
6690         skinframe_t *skinframe;
6691
6692         if (cls.state == ca_dedicated)
6693                 return NULL;
6694
6695         // if already loaded just return it, otherwise make a new skinframe
6696         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6697         if (skinframe && skinframe->base)
6698                 return skinframe;
6699
6700         skinframe->stain = NULL;
6701         skinframe->merged = NULL;
6702         skinframe->base = NULL;
6703         skinframe->pants = NULL;
6704         skinframe->shirt = NULL;
6705         skinframe->nmap = NULL;
6706         skinframe->gloss = NULL;
6707         skinframe->glow = NULL;
6708         skinframe->fog = NULL;
6709         skinframe->reflect = NULL;
6710         skinframe->hasalpha = false;
6711
6712         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6713         if (!skindata)
6714                 return NULL;
6715
6716         if (developer_loading.integer)
6717                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6718
6719         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6720         {
6721                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6722                 temp2 = temp1 + width * height * 4;
6723                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6724                 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);
6725                 Mem_Free(temp1);
6726         }
6727         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6728         if (textureflags & TEXF_ALPHA)
6729         {
6730                 for (i = 3;i < width * height * 4;i += 4)
6731                 {
6732                         if (skindata[i] < 255)
6733                         {
6734                                 skinframe->hasalpha = true;
6735                                 break;
6736                         }
6737                 }
6738                 if (r_loadfog && skinframe->hasalpha)
6739                 {
6740                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6741                         memcpy(fogpixels, skindata, width * height * 4);
6742                         for (i = 0;i < width * height * 4;i += 4)
6743                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6745                         Mem_Free(fogpixels);
6746                 }
6747         }
6748
6749         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6750         //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]);
6751
6752         return skinframe;
6753 }
6754
6755 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6756 {
6757         int i;
6758         int featuresmask;
6759         skinframe_t *skinframe;
6760
6761         if (cls.state == ca_dedicated)
6762                 return NULL;
6763
6764         // if already loaded just return it, otherwise make a new skinframe
6765         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6766         if (skinframe && skinframe->base)
6767                 return skinframe;
6768
6769         skinframe->stain = NULL;
6770         skinframe->merged = NULL;
6771         skinframe->base = NULL;
6772         skinframe->pants = NULL;
6773         skinframe->shirt = NULL;
6774         skinframe->nmap = NULL;
6775         skinframe->gloss = NULL;
6776         skinframe->glow = NULL;
6777         skinframe->fog = NULL;
6778         skinframe->reflect = NULL;
6779         skinframe->hasalpha = false;
6780
6781         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6782         if (!skindata)
6783                 return NULL;
6784
6785         if (developer_loading.integer)
6786                 Con_Printf("loading quake skin \"%s\"\n", name);
6787
6788         // 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)
6789         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6790         memcpy(skinframe->qpixels, skindata, width*height);
6791         skinframe->qwidth = width;
6792         skinframe->qheight = height;
6793
6794         featuresmask = 0;
6795         for (i = 0;i < width * height;i++)
6796                 featuresmask |= palette_featureflags[skindata[i]];
6797
6798         skinframe->hasalpha = false;
6799         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6800         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6801         skinframe->qgeneratemerged = true;
6802         skinframe->qgeneratebase = skinframe->qhascolormapping;
6803         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6804
6805         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6806         //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]);
6807
6808         return skinframe;
6809 }
6810
6811 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6812 {
6813         int width;
6814         int height;
6815         unsigned char *skindata;
6816
6817         if (!skinframe->qpixels)
6818                 return;
6819
6820         if (!skinframe->qhascolormapping)
6821                 colormapped = false;
6822
6823         if (colormapped)
6824         {
6825                 if (!skinframe->qgeneratebase)
6826                         return;
6827         }
6828         else
6829         {
6830                 if (!skinframe->qgeneratemerged)
6831                         return;
6832         }
6833
6834         width = skinframe->qwidth;
6835         height = skinframe->qheight;
6836         skindata = skinframe->qpixels;
6837
6838         if (skinframe->qgeneratenmap)
6839         {
6840                 unsigned char *temp1, *temp2;
6841                 skinframe->qgeneratenmap = false;
6842                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6843                 temp2 = temp1 + width * height * 4;
6844                 // use either a custom palette or the quake palette
6845                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6846                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6847                 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);
6848                 Mem_Free(temp1);
6849         }
6850
6851         if (skinframe->qgenerateglow)
6852         {
6853                 skinframe->qgenerateglow = false;
6854                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6855         }
6856
6857         if (colormapped)
6858         {
6859                 skinframe->qgeneratebase = false;
6860                 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);
6861                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6862                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6863         }
6864         else
6865         {
6866                 skinframe->qgeneratemerged = false;
6867                 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);
6868         }
6869
6870         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6871         {
6872                 Mem_Free(skinframe->qpixels);
6873                 skinframe->qpixels = NULL;
6874         }
6875 }
6876
6877 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)
6878 {
6879         int i;
6880         skinframe_t *skinframe;
6881
6882         if (cls.state == ca_dedicated)
6883                 return NULL;
6884
6885         // if already loaded just return it, otherwise make a new skinframe
6886         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6887         if (skinframe && skinframe->base)
6888                 return skinframe;
6889
6890         skinframe->stain = NULL;
6891         skinframe->merged = NULL;
6892         skinframe->base = NULL;
6893         skinframe->pants = NULL;
6894         skinframe->shirt = NULL;
6895         skinframe->nmap = NULL;
6896         skinframe->gloss = NULL;
6897         skinframe->glow = NULL;
6898         skinframe->fog = NULL;
6899         skinframe->reflect = NULL;
6900         skinframe->hasalpha = false;
6901
6902         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6903         if (!skindata)
6904                 return NULL;
6905
6906         if (developer_loading.integer)
6907                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6908
6909         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6910         if (textureflags & TEXF_ALPHA)
6911         {
6912                 for (i = 0;i < width * height;i++)
6913                 {
6914                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6915                         {
6916                                 skinframe->hasalpha = true;
6917                                 break;
6918                         }
6919                 }
6920                 if (r_loadfog && skinframe->hasalpha)
6921                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6922         }
6923
6924         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6925         //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]);
6926
6927         return skinframe;
6928 }
6929
6930 skinframe_t *R_SkinFrame_LoadMissing(void)
6931 {
6932         skinframe_t *skinframe;
6933
6934         if (cls.state == ca_dedicated)
6935                 return NULL;
6936
6937         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6938         skinframe->stain = NULL;
6939         skinframe->merged = NULL;
6940         skinframe->base = NULL;
6941         skinframe->pants = NULL;
6942         skinframe->shirt = NULL;
6943         skinframe->nmap = NULL;
6944         skinframe->gloss = NULL;
6945         skinframe->glow = NULL;
6946         skinframe->fog = NULL;
6947         skinframe->reflect = NULL;
6948         skinframe->hasalpha = false;
6949
6950         skinframe->avgcolor[0] = rand() / RAND_MAX;
6951         skinframe->avgcolor[1] = rand() / RAND_MAX;
6952         skinframe->avgcolor[2] = rand() / RAND_MAX;
6953         skinframe->avgcolor[3] = 1;
6954
6955         return skinframe;
6956 }
6957
6958 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6959 typedef struct suffixinfo_s
6960 {
6961         const char *suffix;
6962         qboolean flipx, flipy, flipdiagonal;
6963 }
6964 suffixinfo_t;
6965 static suffixinfo_t suffix[3][6] =
6966 {
6967         {
6968                 {"px",   false, false, false},
6969                 {"nx",   false, false, false},
6970                 {"py",   false, false, false},
6971                 {"ny",   false, false, false},
6972                 {"pz",   false, false, false},
6973                 {"nz",   false, false, false}
6974         },
6975         {
6976                 {"posx", false, false, false},
6977                 {"negx", false, false, false},
6978                 {"posy", false, false, false},
6979                 {"negy", false, false, false},
6980                 {"posz", false, false, false},
6981                 {"negz", false, false, false}
6982         },
6983         {
6984                 {"rt",    true, false,  true},
6985                 {"lf",   false,  true,  true},
6986                 {"ft",    true,  true, false},
6987                 {"bk",   false, false, false},
6988                 {"up",    true, false,  true},
6989                 {"dn",    true, false,  true}
6990         }
6991 };
6992
6993 static int componentorder[4] = {0, 1, 2, 3};
6994
6995 rtexture_t *R_LoadCubemap(const char *basename)
6996 {
6997         int i, j, cubemapsize;
6998         unsigned char *cubemappixels, *image_buffer;
6999         rtexture_t *cubemaptexture;
7000         char name[256];
7001         // must start 0 so the first loadimagepixels has no requested width/height
7002         cubemapsize = 0;
7003         cubemappixels = NULL;
7004         cubemaptexture = NULL;
7005         // keep trying different suffix groups (posx, px, rt) until one loads
7006         for (j = 0;j < 3 && !cubemappixels;j++)
7007         {
7008                 // load the 6 images in the suffix group
7009                 for (i = 0;i < 6;i++)
7010                 {
7011                         // generate an image name based on the base and and suffix
7012                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7013                         // load it
7014                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7015                         {
7016                                 // an image loaded, make sure width and height are equal
7017                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7018                                 {
7019                                         // if this is the first image to load successfully, allocate the cubemap memory
7020                                         if (!cubemappixels && image_width >= 1)
7021                                         {
7022                                                 cubemapsize = image_width;
7023                                                 // note this clears to black, so unavailable sides are black
7024                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7025                                         }
7026                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7027                                         if (cubemappixels)
7028                                                 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);
7029                                 }
7030                                 else
7031                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7032                                 // free the image
7033                                 Mem_Free(image_buffer);
7034                         }
7035                 }
7036         }
7037         // if a cubemap loaded, upload it
7038         if (cubemappixels)
7039         {
7040                 if (developer_loading.integer)
7041                         Con_Printf("loading cubemap \"%s\"\n", basename);
7042
7043                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7044                 Mem_Free(cubemappixels);
7045         }
7046         else
7047         {
7048                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7049                 if (developer_loading.integer)
7050                 {
7051                         Con_Printf("(tried tried images ");
7052                         for (j = 0;j < 3;j++)
7053                                 for (i = 0;i < 6;i++)
7054                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7055                         Con_Print(" and was unable to find any of them).\n");
7056                 }
7057         }
7058         return cubemaptexture;
7059 }
7060
7061 rtexture_t *R_GetCubemap(const char *basename)
7062 {
7063         int i;
7064         for (i = 0;i < r_texture_numcubemaps;i++)
7065                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7066                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7067         if (i >= MAX_CUBEMAPS)
7068                 return r_texture_whitecube;
7069         r_texture_numcubemaps++;
7070         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7071         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7072         return r_texture_cubemaps[i].texture;
7073 }
7074
7075 void R_FreeCubemaps(void)
7076 {
7077         int i;
7078         for (i = 0;i < r_texture_numcubemaps;i++)
7079         {
7080                 if (developer_loading.integer)
7081                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7082                 if (r_texture_cubemaps[i].texture)
7083                         R_FreeTexture(r_texture_cubemaps[i].texture);
7084         }
7085         r_texture_numcubemaps = 0;
7086 }
7087
7088 void R_Main_FreeViewCache(void)
7089 {
7090         if (r_refdef.viewcache.entityvisible)
7091                 Mem_Free(r_refdef.viewcache.entityvisible);
7092         if (r_refdef.viewcache.world_pvsbits)
7093                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7094         if (r_refdef.viewcache.world_leafvisible)
7095                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7096         if (r_refdef.viewcache.world_surfacevisible)
7097                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7098         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7099 }
7100
7101 void R_Main_ResizeViewCache(void)
7102 {
7103         int numentities = r_refdef.scene.numentities;
7104         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7105         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7106         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7107         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7108         if (r_refdef.viewcache.maxentities < numentities)
7109         {
7110                 r_refdef.viewcache.maxentities = numentities;
7111                 if (r_refdef.viewcache.entityvisible)
7112                         Mem_Free(r_refdef.viewcache.entityvisible);
7113                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7114         }
7115         if (r_refdef.viewcache.world_numclusters != numclusters)
7116         {
7117                 r_refdef.viewcache.world_numclusters = numclusters;
7118                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7119                 if (r_refdef.viewcache.world_pvsbits)
7120                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7121                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7122         }
7123         if (r_refdef.viewcache.world_numleafs != numleafs)
7124         {
7125                 r_refdef.viewcache.world_numleafs = numleafs;
7126                 if (r_refdef.viewcache.world_leafvisible)
7127                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7128                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7129         }
7130         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7131         {
7132                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7133                 if (r_refdef.viewcache.world_surfacevisible)
7134                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7135                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7136         }
7137 }
7138
7139 extern rtexture_t *loadingscreentexture;
7140 void gl_main_start(void)
7141 {
7142         loadingscreentexture = NULL;
7143         r_texture_blanknormalmap = NULL;
7144         r_texture_white = NULL;
7145         r_texture_grey128 = NULL;
7146         r_texture_black = NULL;
7147         r_texture_whitecube = NULL;
7148         r_texture_normalizationcube = NULL;
7149         r_texture_fogattenuation = NULL;
7150         r_texture_fogheighttexture = NULL;
7151         r_texture_gammaramps = NULL;
7152         r_texture_numcubemaps = 0;
7153
7154         r_loaddds = r_texture_dds_load.integer;
7155         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7156
7157         switch(vid.renderpath)
7158         {
7159         case RENDERPATH_GL20:
7160         case RENDERPATH_CGGL:
7161         case RENDERPATH_D3D9:
7162         case RENDERPATH_D3D10:
7163         case RENDERPATH_D3D11:
7164                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7165                 Cvar_SetValueQuick(&gl_combine, 1);
7166                 Cvar_SetValueQuick(&r_glsl, 1);
7167                 r_loadnormalmap = true;
7168                 r_loadgloss = true;
7169                 r_loadfog = false;
7170                 break;
7171         case RENDERPATH_GL13:
7172                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7173                 Cvar_SetValueQuick(&gl_combine, 1);
7174                 Cvar_SetValueQuick(&r_glsl, 0);
7175                 r_loadnormalmap = false;
7176                 r_loadgloss = false;
7177                 r_loadfog = true;
7178                 break;
7179         case RENDERPATH_GL11:
7180                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7181                 Cvar_SetValueQuick(&gl_combine, 0);
7182                 Cvar_SetValueQuick(&r_glsl, 0);
7183                 r_loadnormalmap = false;
7184                 r_loadgloss = false;
7185                 r_loadfog = true;
7186                 break;
7187         }
7188
7189         R_AnimCache_Free();
7190         R_FrameData_Reset();
7191
7192         r_numqueries = 0;
7193         r_maxqueries = 0;
7194         memset(r_queries, 0, sizeof(r_queries));
7195
7196         r_qwskincache = NULL;
7197         r_qwskincache_size = 0;
7198
7199         // set up r_skinframe loading system for textures
7200         memset(&r_skinframe, 0, sizeof(r_skinframe));
7201         r_skinframe.loadsequence = 1;
7202         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7203
7204         r_main_texturepool = R_AllocTexturePool();
7205         R_BuildBlankTextures();
7206         R_BuildNoTexture();
7207         if (vid.support.arb_texture_cube_map)
7208         {
7209                 R_BuildWhiteCube();
7210                 R_BuildNormalizationCube();
7211         }
7212         r_texture_fogattenuation = NULL;
7213         r_texture_fogheighttexture = NULL;
7214         r_texture_gammaramps = NULL;
7215         //r_texture_fogintensity = NULL;
7216         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7217         memset(&r_waterstate, 0, sizeof(r_waterstate));
7218         r_glsl_permutation = NULL;
7219         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7220         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7221         glslshaderstring = NULL;
7222 #ifdef SUPPORTCG
7223         r_cg_permutation = NULL;
7224         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7225         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7226         cgshaderstring = NULL;
7227 #endif
7228 #ifdef SUPPORTD3D
7229         r_hlsl_permutation = NULL;
7230         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7231         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7232         hlslshaderstring = NULL;
7233 #endif
7234         memset(&r_svbsp, 0, sizeof (r_svbsp));
7235
7236         r_refdef.fogmasktable_density = 0;
7237 }
7238
7239 void gl_main_shutdown(void)
7240 {
7241         R_AnimCache_Free();
7242         R_FrameData_Reset();
7243
7244         R_Main_FreeViewCache();
7245
7246         switch(vid.renderpath)
7247         {
7248         case RENDERPATH_GL11:
7249         case RENDERPATH_GL13:
7250         case RENDERPATH_GL20:
7251         case RENDERPATH_CGGL:
7252                 if (r_maxqueries)
7253                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7254                 break;
7255         case RENDERPATH_D3D9:
7256                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7257                 break;
7258         case RENDERPATH_D3D10:
7259                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7260                 break;
7261         case RENDERPATH_D3D11:
7262                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7263                 break;
7264         }
7265
7266         r_numqueries = 0;
7267         r_maxqueries = 0;
7268         memset(r_queries, 0, sizeof(r_queries));
7269
7270         r_qwskincache = NULL;
7271         r_qwskincache_size = 0;
7272
7273         // clear out the r_skinframe state
7274         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7275         memset(&r_skinframe, 0, sizeof(r_skinframe));
7276
7277         if (r_svbsp.nodes)
7278                 Mem_Free(r_svbsp.nodes);
7279         memset(&r_svbsp, 0, sizeof (r_svbsp));
7280         R_FreeTexturePool(&r_main_texturepool);
7281         loadingscreentexture = NULL;
7282         r_texture_blanknormalmap = NULL;
7283         r_texture_white = NULL;
7284         r_texture_grey128 = NULL;
7285         r_texture_black = NULL;
7286         r_texture_whitecube = NULL;
7287         r_texture_normalizationcube = NULL;
7288         r_texture_fogattenuation = NULL;
7289         r_texture_fogheighttexture = NULL;
7290         r_texture_gammaramps = NULL;
7291         r_texture_numcubemaps = 0;
7292         //r_texture_fogintensity = NULL;
7293         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7294         memset(&r_waterstate, 0, sizeof(r_waterstate));
7295         R_GLSL_Restart_f();
7296
7297         r_glsl_permutation = NULL;
7298         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7299         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7300         glslshaderstring = NULL;
7301 #ifdef SUPPORTCG
7302         r_cg_permutation = NULL;
7303         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7304         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7305         cgshaderstring = NULL;
7306 #endif
7307 #ifdef SUPPORTD3D
7308         r_hlsl_permutation = NULL;
7309         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7310         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7311         hlslshaderstring = NULL;
7312 #endif
7313 }
7314
7315 extern void CL_ParseEntityLump(char *entitystring);
7316 void gl_main_newmap(void)
7317 {
7318         // FIXME: move this code to client
7319         char *entities, entname[MAX_QPATH];
7320         if (r_qwskincache)
7321                 Mem_Free(r_qwskincache);
7322         r_qwskincache = NULL;
7323         r_qwskincache_size = 0;
7324         if (cl.worldmodel)
7325         {
7326                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7327                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7328                 {
7329                         CL_ParseEntityLump(entities);
7330                         Mem_Free(entities);
7331                         return;
7332                 }
7333                 if (cl.worldmodel->brush.entities)
7334                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7335         }
7336         R_Main_FreeViewCache();
7337
7338         R_FrameData_Reset();
7339 }
7340
7341 void GL_Main_Init(void)
7342 {
7343         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7344
7345         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7346         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7347         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7348         if (gamemode == GAME_NEHAHRA)
7349         {
7350                 Cvar_RegisterVariable (&gl_fogenable);
7351                 Cvar_RegisterVariable (&gl_fogdensity);
7352                 Cvar_RegisterVariable (&gl_fogred);
7353                 Cvar_RegisterVariable (&gl_foggreen);
7354                 Cvar_RegisterVariable (&gl_fogblue);
7355                 Cvar_RegisterVariable (&gl_fogstart);
7356                 Cvar_RegisterVariable (&gl_fogend);
7357                 Cvar_RegisterVariable (&gl_skyclip);
7358         }
7359         Cvar_RegisterVariable(&r_motionblur);
7360         Cvar_RegisterVariable(&r_motionblur_maxblur);
7361         Cvar_RegisterVariable(&r_motionblur_bmin);
7362         Cvar_RegisterVariable(&r_motionblur_vmin);
7363         Cvar_RegisterVariable(&r_motionblur_vmax);
7364         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7365         Cvar_RegisterVariable(&r_motionblur_randomize);
7366         Cvar_RegisterVariable(&r_damageblur);
7367         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7368         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7369         Cvar_RegisterVariable(&r_equalize_entities_by);
7370         Cvar_RegisterVariable(&r_equalize_entities_to);
7371         Cvar_RegisterVariable(&r_depthfirst);
7372         Cvar_RegisterVariable(&r_useinfinitefarclip);
7373         Cvar_RegisterVariable(&r_farclip_base);
7374         Cvar_RegisterVariable(&r_farclip_world);
7375         Cvar_RegisterVariable(&r_nearclip);
7376         Cvar_RegisterVariable(&r_showbboxes);
7377         Cvar_RegisterVariable(&r_showsurfaces);
7378         Cvar_RegisterVariable(&r_showtris);
7379         Cvar_RegisterVariable(&r_shownormals);
7380         Cvar_RegisterVariable(&r_showlighting);
7381         Cvar_RegisterVariable(&r_showshadowvolumes);
7382         Cvar_RegisterVariable(&r_showcollisionbrushes);
7383         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7384         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7385         Cvar_RegisterVariable(&r_showdisabledepthtest);
7386         Cvar_RegisterVariable(&r_drawportals);
7387         Cvar_RegisterVariable(&r_drawentities);
7388         Cvar_RegisterVariable(&r_draw2d);
7389         Cvar_RegisterVariable(&r_drawworld);
7390         Cvar_RegisterVariable(&r_cullentities_trace);
7391         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7392         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7393         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7394         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7395         Cvar_RegisterVariable(&r_drawviewmodel);
7396         Cvar_RegisterVariable(&r_drawexteriormodel);
7397         Cvar_RegisterVariable(&r_speeds);
7398         Cvar_RegisterVariable(&r_fullbrights);
7399         Cvar_RegisterVariable(&r_wateralpha);
7400         Cvar_RegisterVariable(&r_dynamic);
7401         Cvar_RegisterVariable(&r_fakelight);
7402         Cvar_RegisterVariable(&r_fakelight_intensity);
7403         Cvar_RegisterVariable(&r_fullbright);
7404         Cvar_RegisterVariable(&r_shadows);
7405         Cvar_RegisterVariable(&r_shadows_darken);
7406         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7407         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7408         Cvar_RegisterVariable(&r_shadows_throwdistance);
7409         Cvar_RegisterVariable(&r_shadows_throwdirection);
7410         Cvar_RegisterVariable(&r_shadows_focus);
7411         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7412         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7413         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7414         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7415         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7416         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7417         Cvar_RegisterVariable(&r_fog_exp2);
7418         Cvar_RegisterVariable(&r_drawfog);
7419         Cvar_RegisterVariable(&r_transparentdepthmasking);
7420         Cvar_RegisterVariable(&r_texture_dds_load);
7421         Cvar_RegisterVariable(&r_texture_dds_save);
7422         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7423         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7424         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7425         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7426         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7427         Cvar_RegisterVariable(&r_textureunits);
7428         Cvar_RegisterVariable(&gl_combine);
7429         Cvar_RegisterVariable(&r_glsl);
7430         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7431         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7432         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7433         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7434         Cvar_RegisterVariable(&r_glsl_postprocess);
7435         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7436         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7437         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7438         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7439         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7440         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7441         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7442         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7443
7444         Cvar_RegisterVariable(&r_water);
7445         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7446         Cvar_RegisterVariable(&r_water_clippingplanebias);
7447         Cvar_RegisterVariable(&r_water_refractdistort);
7448         Cvar_RegisterVariable(&r_water_reflectdistort);
7449         Cvar_RegisterVariable(&r_water_scissormode);
7450         Cvar_RegisterVariable(&r_lerpsprites);
7451         Cvar_RegisterVariable(&r_lerpmodels);
7452         Cvar_RegisterVariable(&r_lerplightstyles);
7453         Cvar_RegisterVariable(&r_waterscroll);
7454         Cvar_RegisterVariable(&r_bloom);
7455         Cvar_RegisterVariable(&r_bloom_colorscale);
7456         Cvar_RegisterVariable(&r_bloom_brighten);
7457         Cvar_RegisterVariable(&r_bloom_blur);
7458         Cvar_RegisterVariable(&r_bloom_resolution);
7459         Cvar_RegisterVariable(&r_bloom_colorexponent);
7460         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7461         Cvar_RegisterVariable(&r_hdr);
7462         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7463         Cvar_RegisterVariable(&r_hdr_glowintensity);
7464         Cvar_RegisterVariable(&r_hdr_range);
7465         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7466         Cvar_RegisterVariable(&developer_texturelogging);
7467         Cvar_RegisterVariable(&gl_lightmaps);
7468         Cvar_RegisterVariable(&r_test);
7469         Cvar_RegisterVariable(&r_glsl_saturation);
7470         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7471         Cvar_RegisterVariable(&r_framedatasize);
7472         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7473                 Cvar_SetValue("r_fullbrights", 0);
7474         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7475
7476         Cvar_RegisterVariable(&r_track_sprites);
7477         Cvar_RegisterVariable(&r_track_sprites_flags);
7478         Cvar_RegisterVariable(&r_track_sprites_scalew);
7479         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7480         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7481         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7482         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7483         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7484 }
7485
7486 extern void R_Textures_Init(void);
7487 extern void GL_Draw_Init(void);
7488 extern void GL_Main_Init(void);
7489 extern void R_Shadow_Init(void);
7490 extern void R_Sky_Init(void);
7491 extern void GL_Surf_Init(void);
7492 extern void R_Particles_Init(void);
7493 extern void R_Explosion_Init(void);
7494 extern void gl_backend_init(void);
7495 extern void Sbar_Init(void);
7496 extern void R_LightningBeams_Init(void);
7497 extern void Mod_RenderInit(void);
7498 extern void Font_Init(void);
7499
7500 void Render_Init(void)
7501 {
7502         gl_backend_init();
7503         R_Textures_Init();
7504         GL_Main_Init();
7505         Font_Init();
7506         GL_Draw_Init();
7507         R_Shadow_Init();
7508         R_Sky_Init();
7509         GL_Surf_Init();
7510         Sbar_Init();
7511         R_Particles_Init();
7512         R_Explosion_Init();
7513         R_LightningBeams_Init();
7514         Mod_RenderInit();
7515 }
7516
7517 /*
7518 ===============
7519 GL_Init
7520 ===============
7521 */
7522 extern char *ENGINE_EXTENSIONS;
7523 void GL_Init (void)
7524 {
7525         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7526         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7527         gl_version = (const char *)qglGetString(GL_VERSION);
7528         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7529
7530         if (!gl_extensions)
7531                 gl_extensions = "";
7532         if (!gl_platformextensions)
7533                 gl_platformextensions = "";
7534
7535         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7536         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7537         Con_Printf("GL_VERSION: %s\n", gl_version);
7538         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7539         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7540
7541         VID_CheckExtensions();
7542
7543         // LordHavoc: report supported extensions
7544         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7545
7546         // clear to black (loading plaque will be seen over this)
7547         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7548 }
7549
7550 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7551 {
7552         int i;
7553         mplane_t *p;
7554         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7555         {
7556                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7557                 if (i == 4)
7558                         continue;
7559                 p = r_refdef.view.frustum + i;
7560                 switch(p->signbits)
7561                 {
7562                 default:
7563                 case 0:
7564                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7565                                 return true;
7566                         break;
7567                 case 1:
7568                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7569                                 return true;
7570                         break;
7571                 case 2:
7572                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7573                                 return true;
7574                         break;
7575                 case 3:
7576                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7577                                 return true;
7578                         break;
7579                 case 4:
7580                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7581                                 return true;
7582                         break;
7583                 case 5:
7584                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7585                                 return true;
7586                         break;
7587                 case 6:
7588                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7589                                 return true;
7590                         break;
7591                 case 7:
7592                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7593                                 return true;
7594                         break;
7595                 }
7596         }
7597         return false;
7598 }
7599
7600 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7601 {
7602         int i;
7603         const mplane_t *p;
7604         for (i = 0;i < numplanes;i++)
7605         {
7606                 p = planes + i;
7607                 switch(p->signbits)
7608                 {
7609                 default:
7610                 case 0:
7611                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7612                                 return true;
7613                         break;
7614                 case 1:
7615                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7616                                 return true;
7617                         break;
7618                 case 2:
7619                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7620                                 return true;
7621                         break;
7622                 case 3:
7623                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7624                                 return true;
7625                         break;
7626                 case 4:
7627                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7628                                 return true;
7629                         break;
7630                 case 5:
7631                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7632                                 return true;
7633                         break;
7634                 case 6:
7635                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7636                                 return true;
7637                         break;
7638                 case 7:
7639                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7640                                 return true;
7641                         break;
7642                 }
7643         }
7644         return false;
7645 }
7646
7647 //==================================================================================
7648
7649 // LordHavoc: this stores temporary data used within the same frame
7650
7651 qboolean r_framedata_failed;
7652 static size_t r_framedata_size;
7653 static size_t r_framedata_current;
7654 static void *r_framedata_base;
7655
7656 void R_FrameData_Reset(void)
7657 {
7658         if (r_framedata_base)
7659                 Mem_Free(r_framedata_base);
7660         r_framedata_base = NULL;
7661         r_framedata_size = 0;
7662         r_framedata_current = 0;
7663         r_framedata_failed = false;
7664 }
7665
7666 void R_FrameData_NewFrame(void)
7667 {
7668         size_t wantedsize;
7669         if (r_framedata_failed)
7670                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7671         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7672         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7673         if (r_framedata_size != wantedsize)
7674         {
7675                 r_framedata_size = wantedsize;
7676                 if (r_framedata_base)
7677                         Mem_Free(r_framedata_base);
7678                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7679         }
7680         r_framedata_current = 0;
7681         r_framedata_failed = false;
7682 }
7683
7684 void *R_FrameData_Alloc(size_t size)
7685 {
7686         void *data;
7687
7688         // align to 16 byte boundary
7689         size = (size + 15) & ~15;
7690         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7691         r_framedata_current += size;
7692
7693         // check overflow
7694         if (r_framedata_current > r_framedata_size)
7695                 r_framedata_failed = true;
7696
7697         // return NULL on everything after a failure
7698         if (r_framedata_failed)
7699                 return NULL;
7700
7701         return data;
7702 }
7703
7704 void *R_FrameData_Store(size_t size, void *data)
7705 {
7706         void *d = R_FrameData_Alloc(size);
7707         if (d)
7708                 memcpy(d, data, size);
7709         return d;
7710 }
7711
7712 //==================================================================================
7713
7714 // LordHavoc: animcache originally written by Echon, rewritten since then
7715
7716 /**
7717  * Animation cache prevents re-generating mesh data for an animated model
7718  * multiple times in one frame for lighting, shadowing, reflections, etc.
7719  */
7720
7721 void R_AnimCache_Free(void)
7722 {
7723 }
7724
7725 void R_AnimCache_ClearCache(void)
7726 {
7727         int i;
7728         entity_render_t *ent;
7729
7730         for (i = 0;i < r_refdef.scene.numentities;i++)
7731         {
7732                 ent = r_refdef.scene.entities[i];
7733                 ent->animcache_vertex3f = NULL;
7734                 ent->animcache_normal3f = NULL;
7735                 ent->animcache_svector3f = NULL;
7736                 ent->animcache_tvector3f = NULL;
7737                 ent->animcache_vertexposition = NULL;
7738                 ent->animcache_vertexmesh = NULL;
7739                 ent->animcache_vertexpositionbuffer = NULL;
7740                 ent->animcache_vertexmeshbuffer = NULL;
7741         }
7742 }
7743
7744 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7745 {
7746         int i;
7747
7748         // identical memory layout, so no need to allocate...
7749         // this also provides the vertexposition structure to everything, e.g.
7750         // depth masked rendering currently uses it even if having separate
7751         // arrays
7752         // NOTE: get rid of this optimization if changing it to e.g. 4f
7753         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7754
7755         // TODO:
7756         // get rid of following uses of VERTEXPOSITION, change to the array:
7757         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7758         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7759         // R_DrawTextureSurfaceList_DepthOnly
7760         // R_Q1BSP_DrawShadowMap
7761
7762         switch(vid.renderpath)
7763         {
7764         case RENDERPATH_GL20:
7765         case RENDERPATH_CGGL:
7766                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7767                 if (gl_mesh_separatearrays.integer)
7768                         return;
7769                 break;
7770         case RENDERPATH_D3D9:
7771         case RENDERPATH_D3D10:
7772         case RENDERPATH_D3D11:
7773                 // always need the meshbuffers
7774                 break;
7775         case RENDERPATH_GL13:
7776         case RENDERPATH_GL11:
7777                 // never need the meshbuffers
7778                 return;
7779         }
7780
7781         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7782                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7783         /*
7784         if (!ent->animcache_vertexposition)
7785                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7786         */
7787         if (ent->animcache_vertexposition)
7788         {
7789                 /*
7790                 for (i = 0;i < numvertices;i++)
7791                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7792                 */
7793                 // TODO: upload vertex buffer?
7794         }
7795         if (ent->animcache_vertexmesh)
7796         {
7797                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7798                 for (i = 0;i < numvertices;i++)
7799                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7800                 if (ent->animcache_svector3f)
7801                         for (i = 0;i < numvertices;i++)
7802                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7803                 if (ent->animcache_tvector3f)
7804                         for (i = 0;i < numvertices;i++)
7805                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7806                 if (ent->animcache_normal3f)
7807                         for (i = 0;i < numvertices;i++)
7808                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7809                 // TODO: upload vertex buffer?
7810         }
7811 }
7812
7813 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7814 {
7815         dp_model_t *model = ent->model;
7816         int numvertices;
7817         // see if it's already cached this frame
7818         if (ent->animcache_vertex3f)
7819         {
7820                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7821                 if (wantnormals || wanttangents)
7822                 {
7823                         if (ent->animcache_normal3f)
7824                                 wantnormals = false;
7825                         if (ent->animcache_svector3f)
7826                                 wanttangents = false;
7827                         if (wantnormals || wanttangents)
7828                         {
7829                                 numvertices = model->surfmesh.num_vertices;
7830                                 if (wantnormals)
7831                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7832                                 if (wanttangents)
7833                                 {
7834                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7835                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7836                                 }
7837                                 if (!r_framedata_failed)
7838                                 {
7839                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7840                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7841                                 }
7842                         }
7843                 }
7844         }
7845         else
7846         {
7847                 // see if this ent is worth caching
7848                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7849                         return false;
7850                 // get some memory for this entity and generate mesh data
7851                 numvertices = model->surfmesh.num_vertices;
7852                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7853                 if (wantnormals)
7854                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7855                 if (wanttangents)
7856                 {
7857                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7858                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7859                 }
7860                 if (!r_framedata_failed)
7861                 {
7862                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7863                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7864                 }
7865         }
7866         return !r_framedata_failed;
7867 }
7868
7869 void R_AnimCache_CacheVisibleEntities(void)
7870 {
7871         int i;
7872         qboolean wantnormals = true;
7873         qboolean wanttangents = !r_showsurfaces.integer;
7874
7875         switch(vid.renderpath)
7876         {
7877         case RENDERPATH_GL20:
7878         case RENDERPATH_CGGL:
7879         case RENDERPATH_D3D9:
7880         case RENDERPATH_D3D10:
7881         case RENDERPATH_D3D11:
7882                 break;
7883         case RENDERPATH_GL13:
7884         case RENDERPATH_GL11:
7885                 wanttangents = false;
7886                 break;
7887         }
7888
7889         if (r_shownormals.integer)
7890                 wanttangents = wantnormals = true;
7891
7892         // TODO: thread this
7893         // NOTE: R_PrepareRTLights() also caches entities
7894
7895         for (i = 0;i < r_refdef.scene.numentities;i++)
7896                 if (r_refdef.viewcache.entityvisible[i])
7897                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7898 }
7899
7900 //==================================================================================
7901
7902 static void R_View_UpdateEntityLighting (void)
7903 {
7904         int i;
7905         entity_render_t *ent;
7906         vec3_t tempdiffusenormal, avg;
7907         vec_t f, fa, fd, fdd;
7908         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7909
7910         for (i = 0;i < r_refdef.scene.numentities;i++)
7911         {
7912                 ent = r_refdef.scene.entities[i];
7913
7914                 // skip unseen models
7915                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7916                         continue;
7917
7918                 // skip bsp models
7919                 if (ent->model && ent->model->brush.num_leafs)
7920                 {
7921                         // TODO: use modellight for r_ambient settings on world?
7922                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7923                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7924                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7925                         continue;
7926                 }
7927
7928                 // fetch the lighting from the worldmodel data
7929                 VectorClear(ent->modellight_ambient);
7930                 VectorClear(ent->modellight_diffuse);
7931                 VectorClear(tempdiffusenormal);
7932                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7933                 {
7934                         vec3_t org;
7935                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7936
7937                         // complete lightning for lit sprites
7938                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7939                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7940                         {
7941                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7942                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7943                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7944                         }
7945                         else
7946                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7947
7948                         if(ent->flags & RENDER_EQUALIZE)
7949                         {
7950                                 // first fix up ambient lighting...
7951                                 if(r_equalize_entities_minambient.value > 0)
7952                                 {
7953                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7954                                         if(fd > 0)
7955                                         {
7956                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7957                                                 if(fa < r_equalize_entities_minambient.value * fd)
7958                                                 {
7959                                                         // solve:
7960                                                         //   fa'/fd' = minambient
7961                                                         //   fa'+0.25*fd' = fa+0.25*fd
7962                                                         //   ...
7963                                                         //   fa' = fd' * minambient
7964                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7965                                                         //   ...
7966                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7967                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7968                                                         //   ...
7969                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7970                                                         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
7971                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7972                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7973                                                 }
7974                                         }
7975                                 }
7976
7977                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7978                                 {
7979                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7980                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7981                                         f = fa + 0.25 * fd;
7982                                         if(f > 0)
7983                                         {
7984                                                 // adjust brightness and saturation to target
7985                                                 avg[0] = avg[1] = avg[2] = fa / f;
7986                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7987                                                 avg[0] = avg[1] = avg[2] = fd / f;
7988                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7989                                         }
7990                                 }
7991                         }
7992                 }
7993                 else // highly rare
7994                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7995
7996                 // move the light direction into modelspace coordinates for lighting code
7997                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7998                 if(VectorLength2(ent->modellight_lightdir) == 0)
7999                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8000                 VectorNormalize(ent->modellight_lightdir);
8001         }
8002 }
8003
8004 #define MAX_LINEOFSIGHTTRACES 64
8005
8006 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8007 {
8008         int i;
8009         vec3_t boxmins, boxmaxs;
8010         vec3_t start;
8011         vec3_t end;
8012         dp_model_t *model = r_refdef.scene.worldmodel;
8013
8014         if (!model || !model->brush.TraceLineOfSight)
8015                 return true;
8016
8017         // expand the box a little
8018         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8019         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8020         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8021         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8022         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8023         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8024
8025         // return true if eye is inside enlarged box
8026         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8027                 return true;
8028
8029         // try center
8030         VectorCopy(eye, start);
8031         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8032         if (model->brush.TraceLineOfSight(model, start, end))
8033                 return true;
8034
8035         // try various random positions
8036         for (i = 0;i < numsamples;i++)
8037         {
8038                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8039                 if (model->brush.TraceLineOfSight(model, start, end))
8040                         return true;
8041         }
8042
8043         return false;
8044 }
8045
8046
8047 static void R_View_UpdateEntityVisible (void)
8048 {
8049         int i;
8050         int renderimask;
8051         int samples;
8052         entity_render_t *ent;
8053
8054         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8055                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8056                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8057                 :                                                          RENDER_EXTERIORMODEL;
8058         if (!r_drawviewmodel.integer)
8059                 renderimask |= RENDER_VIEWMODEL;
8060         if (!r_drawexteriormodel.integer)
8061                 renderimask |= RENDER_EXTERIORMODEL;
8062         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8063         {
8064                 // worldmodel can check visibility
8065                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8066                 for (i = 0;i < r_refdef.scene.numentities;i++)
8067                 {
8068                         ent = r_refdef.scene.entities[i];
8069                         if (!(ent->flags & renderimask))
8070                         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)))
8071                         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))
8072                                 r_refdef.viewcache.entityvisible[i] = true;
8073                 }
8074                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8075                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8076                 {
8077                         for (i = 0;i < r_refdef.scene.numentities;i++)
8078                         {
8079                                 ent = r_refdef.scene.entities[i];
8080                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8081                                 {
8082                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8083                                         if (samples < 0)
8084                                                 continue; // temp entities do pvs only
8085                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8086                                                 ent->last_trace_visibility = realtime;
8087                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8088                                                 r_refdef.viewcache.entityvisible[i] = 0;
8089                                 }
8090                         }
8091                 }
8092         }
8093         else
8094         {
8095                 // no worldmodel or it can't check visibility
8096                 for (i = 0;i < r_refdef.scene.numentities;i++)
8097                 {
8098                         ent = r_refdef.scene.entities[i];
8099                         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));
8100                 }
8101         }
8102 }
8103
8104 /// only used if skyrendermasked, and normally returns false
8105 int R_DrawBrushModelsSky (void)
8106 {
8107         int i, sky;
8108         entity_render_t *ent;
8109
8110         sky = false;
8111         for (i = 0;i < r_refdef.scene.numentities;i++)
8112         {
8113                 if (!r_refdef.viewcache.entityvisible[i])
8114                         continue;
8115                 ent = r_refdef.scene.entities[i];
8116                 if (!ent->model || !ent->model->DrawSky)
8117                         continue;
8118                 ent->model->DrawSky(ent);
8119                 sky = true;
8120         }
8121         return sky;
8122 }
8123
8124 static void R_DrawNoModel(entity_render_t *ent);
8125 static void R_DrawModels(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                 r_refdef.stats.entities++;
8136                 if (ent->model && ent->model->Draw != NULL)
8137                         ent->model->Draw(ent);
8138                 else
8139                         R_DrawNoModel(ent);
8140         }
8141 }
8142
8143 static void R_DrawModelsDepth(void)
8144 {
8145         int i;
8146         entity_render_t *ent;
8147
8148         for (i = 0;i < r_refdef.scene.numentities;i++)
8149         {
8150                 if (!r_refdef.viewcache.entityvisible[i])
8151                         continue;
8152                 ent = r_refdef.scene.entities[i];
8153                 if (ent->model && ent->model->DrawDepth != NULL)
8154                         ent->model->DrawDepth(ent);
8155         }
8156 }
8157
8158 static void R_DrawModelsDebug(void)
8159 {
8160         int i;
8161         entity_render_t *ent;
8162
8163         for (i = 0;i < r_refdef.scene.numentities;i++)
8164         {
8165                 if (!r_refdef.viewcache.entityvisible[i])
8166                         continue;
8167                 ent = r_refdef.scene.entities[i];
8168                 if (ent->model && ent->model->DrawDebug != NULL)
8169                         ent->model->DrawDebug(ent);
8170         }
8171 }
8172
8173 static void R_DrawModelsAddWaterPlanes(void)
8174 {
8175         int i;
8176         entity_render_t *ent;
8177
8178         for (i = 0;i < r_refdef.scene.numentities;i++)
8179         {
8180                 if (!r_refdef.viewcache.entityvisible[i])
8181                         continue;
8182                 ent = r_refdef.scene.entities[i];
8183                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8184                         ent->model->DrawAddWaterPlanes(ent);
8185         }
8186 }
8187
8188 static void R_View_SetFrustum(const int *scissor)
8189 {
8190         int i;
8191         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8192         vec3_t forward, left, up, origin, v;
8193
8194         if(scissor)
8195         {
8196                 // flipped x coordinates (because x points left here)
8197                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8198                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8199
8200                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8201                 switch(vid.renderpath)
8202                 {
8203                         case RENDERPATH_D3D9:
8204                         case RENDERPATH_D3D10:
8205                         case RENDERPATH_D3D11:
8206                                 // non-flipped y coordinates
8207                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8208                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8209                                 break;
8210                         case RENDERPATH_GL11:
8211                         case RENDERPATH_GL13:
8212                         case RENDERPATH_GL20:
8213                         case RENDERPATH_CGGL:
8214                                 // non-flipped y coordinates
8215                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8216                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8217                                 break;
8218                 }
8219         }
8220
8221         // we can't trust r_refdef.view.forward and friends in reflected scenes
8222         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8223
8224 #if 0
8225         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8226         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8227         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8228         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8229         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8230         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8231         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8232         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8233         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8234         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8235         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8236         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8237 #endif
8238
8239 #if 0
8240         zNear = r_refdef.nearclip;
8241         nudge = 1.0 - 1.0 / (1<<23);
8242         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8243         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8244         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8245         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8246         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8247         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8248         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8249         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8250 #endif
8251
8252
8253
8254 #if 0
8255         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8256         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8257         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8258         r_refdef.view.frustum[0].dist = m[15] - m[12];
8259
8260         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8261         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8262         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8263         r_refdef.view.frustum[1].dist = m[15] + m[12];
8264
8265         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8266         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8267         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8268         r_refdef.view.frustum[2].dist = m[15] - m[13];
8269
8270         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8271         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8272         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8273         r_refdef.view.frustum[3].dist = m[15] + m[13];
8274
8275         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8276         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8277         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8278         r_refdef.view.frustum[4].dist = m[15] - m[14];
8279
8280         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8281         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8282         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8283         r_refdef.view.frustum[5].dist = m[15] + m[14];
8284 #endif
8285
8286         if (r_refdef.view.useperspective)
8287         {
8288                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8289                 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]);
8290                 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]);
8291                 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]);
8292                 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]);
8293
8294                 // then the normals from the corners relative to origin
8295                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8296                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8297                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8298                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8299
8300                 // in a NORMAL view, forward cross left == up
8301                 // in a REFLECTED view, forward cross left == down
8302                 // so our cross products above need to be adjusted for a left handed coordinate system
8303                 CrossProduct(forward, left, v);
8304                 if(DotProduct(v, up) < 0)
8305                 {
8306                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8307                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8308                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8309                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8310                 }
8311
8312                 // Leaving those out was a mistake, those were in the old code, and they
8313                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8314                 // I couldn't reproduce it after adding those normalizations. --blub
8315                 VectorNormalize(r_refdef.view.frustum[0].normal);
8316                 VectorNormalize(r_refdef.view.frustum[1].normal);
8317                 VectorNormalize(r_refdef.view.frustum[2].normal);
8318                 VectorNormalize(r_refdef.view.frustum[3].normal);
8319
8320                 // make the corners absolute
8321                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8322                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8323                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8324                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8325
8326                 // one more normal
8327                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8328
8329                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8330                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8331                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8332                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8333                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8334         }
8335         else
8336         {
8337                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8338                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8339                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8340                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8341                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8342                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8343                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8344                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8345                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8346                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8347         }
8348         r_refdef.view.numfrustumplanes = 5;
8349
8350         if (r_refdef.view.useclipplane)
8351         {
8352                 r_refdef.view.numfrustumplanes = 6;
8353                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8354         }
8355
8356         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8357                 PlaneClassify(r_refdef.view.frustum + i);
8358
8359         // LordHavoc: note to all quake engine coders, Quake had a special case
8360         // for 90 degrees which assumed a square view (wrong), so I removed it,
8361         // Quake2 has it disabled as well.
8362
8363         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8364         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8365         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8366         //PlaneClassify(&frustum[0]);
8367
8368         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8369         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8370         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8371         //PlaneClassify(&frustum[1]);
8372
8373         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8374         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8375         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8376         //PlaneClassify(&frustum[2]);
8377
8378         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8379         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8380         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8381         //PlaneClassify(&frustum[3]);
8382
8383         // nearclip plane
8384         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8385         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8386         //PlaneClassify(&frustum[4]);
8387 }
8388
8389 void R_View_UpdateWithScissor(const int *myscissor)
8390 {
8391         R_Main_ResizeViewCache();
8392         R_View_SetFrustum(myscissor);
8393         R_View_WorldVisibility(r_refdef.view.useclipplane);
8394         R_View_UpdateEntityVisible();
8395         R_View_UpdateEntityLighting();
8396 }
8397
8398 void R_View_Update(void)
8399 {
8400         R_Main_ResizeViewCache();
8401         R_View_SetFrustum(NULL);
8402         R_View_WorldVisibility(r_refdef.view.useclipplane);
8403         R_View_UpdateEntityVisible();
8404         R_View_UpdateEntityLighting();
8405 }
8406
8407 void R_SetupView(qboolean allowwaterclippingplane)
8408 {
8409         const float *customclipplane = NULL;
8410         float plane[4];
8411         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8412         {
8413                 // LordHavoc: couldn't figure out how to make this approach the
8414                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8415                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8416                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8417                         dist = r_refdef.view.clipplane.dist;
8418                 plane[0] = r_refdef.view.clipplane.normal[0];
8419                 plane[1] = r_refdef.view.clipplane.normal[1];
8420                 plane[2] = r_refdef.view.clipplane.normal[2];
8421                 plane[3] = dist;
8422                 customclipplane = plane;
8423         }
8424
8425         if (!r_refdef.view.useperspective)
8426                 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);
8427         else if (vid.stencil && r_useinfinitefarclip.integer)
8428                 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);
8429         else
8430                 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);
8431         R_SetViewport(&r_refdef.view.viewport);
8432 }
8433
8434 void R_EntityMatrix(const matrix4x4_t *matrix)
8435 {
8436         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8437         {
8438                 gl_modelmatrixchanged = false;
8439                 gl_modelmatrix = *matrix;
8440                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8441                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8442                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8443                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8444                 CHECKGLERROR
8445                 switch(vid.renderpath)
8446                 {
8447                 case RENDERPATH_D3D9:
8448 #ifdef SUPPORTD3D
8449                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8450                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8451 #endif
8452                         break;
8453                 case RENDERPATH_D3D10:
8454                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8455                         break;
8456                 case RENDERPATH_D3D11:
8457                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8458                         break;
8459                 case RENDERPATH_GL20:
8460                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8461                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8462                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8463                         break;
8464                 case RENDERPATH_CGGL:
8465 #ifdef SUPPORTCG
8466                         CHECKCGERROR
8467                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8468                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8469                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8470 #endif
8471                         break;
8472                 case RENDERPATH_GL13:
8473                 case RENDERPATH_GL11:
8474                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8475                         break;
8476                 }
8477         }
8478 }
8479
8480 void R_ResetViewRendering2D(void)
8481 {
8482         r_viewport_t viewport;
8483         DrawQ_Finish();
8484
8485         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8486         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);
8487         R_SetViewport(&viewport);
8488         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8489         GL_Color(1, 1, 1, 1);
8490         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8491         GL_BlendFunc(GL_ONE, GL_ZERO);
8492         GL_AlphaTest(false);
8493         GL_ScissorTest(false);
8494         GL_DepthMask(false);
8495         GL_DepthRange(0, 1);
8496         GL_DepthTest(false);
8497         GL_DepthFunc(GL_LEQUAL);
8498         R_EntityMatrix(&identitymatrix);
8499         R_Mesh_ResetTextureState();
8500         GL_PolygonOffset(0, 0);
8501         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8502         switch(vid.renderpath)
8503         {
8504         case RENDERPATH_GL11:
8505         case RENDERPATH_GL13:
8506         case RENDERPATH_GL20:
8507         case RENDERPATH_CGGL:
8508                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8509                 break;
8510         case RENDERPATH_D3D9:
8511         case RENDERPATH_D3D10:
8512         case RENDERPATH_D3D11:
8513                 break;
8514         }
8515         GL_CullFace(GL_NONE);
8516 }
8517
8518 void R_ResetViewRendering3D(void)
8519 {
8520         DrawQ_Finish();
8521
8522         R_SetupView(true);
8523         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8524         GL_Color(1, 1, 1, 1);
8525         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8526         GL_BlendFunc(GL_ONE, GL_ZERO);
8527         GL_AlphaTest(false);
8528         GL_ScissorTest(true);
8529         GL_DepthMask(true);
8530         GL_DepthRange(0, 1);
8531         GL_DepthTest(true);
8532         GL_DepthFunc(GL_LEQUAL);
8533         R_EntityMatrix(&identitymatrix);
8534         R_Mesh_ResetTextureState();
8535         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8536         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8537         switch(vid.renderpath)
8538         {
8539         case RENDERPATH_GL11:
8540         case RENDERPATH_GL13:
8541         case RENDERPATH_GL20:
8542         case RENDERPATH_CGGL:
8543                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8544                 break;
8545         case RENDERPATH_D3D9:
8546         case RENDERPATH_D3D10:
8547         case RENDERPATH_D3D11:
8548                 break;
8549         }
8550         GL_CullFace(r_refdef.view.cullface_back);
8551 }
8552
8553 /*
8554 ================
8555 R_RenderView_UpdateViewVectors
8556 ================
8557 */
8558 static void R_RenderView_UpdateViewVectors(void)
8559 {
8560         // break apart the view matrix into vectors for various purposes
8561         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8562         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8563         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8564         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8565         // make an inverted copy of the view matrix for tracking sprites
8566         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8567 }
8568
8569 void R_RenderScene(void);
8570 void R_RenderWaterPlanes(void);
8571
8572 static void R_Water_StartFrame(void)
8573 {
8574         int i;
8575         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8576         r_waterstate_waterplane_t *p;
8577
8578         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8579                 return;
8580
8581         switch(vid.renderpath)
8582         {
8583         case RENDERPATH_GL20:
8584         case RENDERPATH_CGGL:
8585         case RENDERPATH_D3D9:
8586         case RENDERPATH_D3D10:
8587         case RENDERPATH_D3D11:
8588                 break;
8589         case RENDERPATH_GL13:
8590         case RENDERPATH_GL11:
8591                 return;
8592         }
8593
8594         // set waterwidth and waterheight to the water resolution that will be
8595         // used (often less than the screen resolution for faster rendering)
8596         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8597         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8598
8599         // calculate desired texture sizes
8600         // can't use water if the card does not support the texture size
8601         if (!r_water.integer || r_showsurfaces.integer)
8602                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8603         else if (vid.support.arb_texture_non_power_of_two)
8604         {
8605                 texturewidth = waterwidth;
8606                 textureheight = waterheight;
8607                 camerawidth = waterwidth;
8608                 cameraheight = waterheight;
8609         }
8610         else
8611         {
8612                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8613                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8614                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8615                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8616         }
8617
8618         // allocate textures as needed
8619         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8620         {
8621                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8622                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8623                 {
8624                         if (p->texture_refraction)
8625                                 R_FreeTexture(p->texture_refraction);
8626                         p->texture_refraction = NULL;
8627                         if (p->texture_reflection)
8628                                 R_FreeTexture(p->texture_reflection);
8629                         p->texture_reflection = NULL;
8630                         if (p->texture_camera)
8631                                 R_FreeTexture(p->texture_camera);
8632                         p->texture_camera = NULL;
8633                 }
8634                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8635                 r_waterstate.texturewidth = texturewidth;
8636                 r_waterstate.textureheight = textureheight;
8637                 r_waterstate.camerawidth = camerawidth;
8638                 r_waterstate.cameraheight = cameraheight;
8639         }
8640
8641         if (r_waterstate.texturewidth)
8642         {
8643                 r_waterstate.enabled = true;
8644
8645                 // when doing a reduced render (HDR) we want to use a smaller area
8646                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8647                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8648
8649                 // set up variables that will be used in shader setup
8650                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8651                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8652                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8653                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8654         }
8655
8656         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8657         r_waterstate.numwaterplanes = 0;
8658 }
8659
8660 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8661 {
8662         int triangleindex, planeindex;
8663         const int *e;
8664         vec3_t vert[3];
8665         vec3_t normal;
8666         vec3_t center;
8667         mplane_t plane;
8668         r_waterstate_waterplane_t *p;
8669         texture_t *t = R_GetCurrentTexture(surface->texture);
8670
8671         // just use the first triangle with a valid normal for any decisions
8672         VectorClear(normal);
8673         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8674         {
8675                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8676                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8677                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8678                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8679                 if (VectorLength2(normal) >= 0.001)
8680                         break;
8681         }
8682
8683         VectorCopy(normal, plane.normal);
8684         VectorNormalize(plane.normal);
8685         plane.dist = DotProduct(vert[0], plane.normal);
8686         PlaneClassify(&plane);
8687         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8688         {
8689                 // skip backfaces (except if nocullface is set)
8690                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8691                         return;
8692                 VectorNegate(plane.normal, plane.normal);
8693                 plane.dist *= -1;
8694                 PlaneClassify(&plane);
8695         }
8696
8697
8698         // find a matching plane if there is one
8699         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8700                 if(p->camera_entity == t->camera_entity)
8701                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8702                                 break;
8703         if (planeindex >= r_waterstate.maxwaterplanes)
8704                 return; // nothing we can do, out of planes
8705
8706         // if this triangle does not fit any known plane rendered this frame, add one
8707         if (planeindex >= r_waterstate.numwaterplanes)
8708         {
8709                 // store the new plane
8710                 r_waterstate.numwaterplanes++;
8711                 p->plane = plane;
8712                 // clear materialflags and pvs
8713                 p->materialflags = 0;
8714                 p->pvsvalid = false;
8715                 p->camera_entity = t->camera_entity;
8716                 VectorCopy(surface->mins, p->mins);
8717                 VectorCopy(surface->maxs, p->maxs);
8718         }
8719         else
8720         {
8721                 // merge mins/maxs
8722                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8723                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8724                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8725                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8726                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8727                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8728         }
8729         // merge this surface's materialflags into the waterplane
8730         p->materialflags |= t->currentmaterialflags;
8731         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8732         {
8733                 // merge this surface's PVS into the waterplane
8734                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8735                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8736                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8737                 {
8738                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8739                         p->pvsvalid = true;
8740                 }
8741         }
8742 }
8743
8744 static void R_Water_ProcessPlanes(void)
8745 {
8746         int myscissor[4];
8747         r_refdef_view_t originalview;
8748         r_refdef_view_t myview;
8749         int planeindex;
8750         r_waterstate_waterplane_t *p;
8751         vec3_t visorigin;
8752
8753         originalview = r_refdef.view;
8754
8755         // make sure enough textures are allocated
8756         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8757         {
8758                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8759                 {
8760                         if (!p->texture_refraction)
8761                                 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);
8762                         if (!p->texture_refraction)
8763                                 goto error;
8764                 }
8765                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8766                 {
8767                         if (!p->texture_camera)
8768                                 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);
8769                         if (!p->texture_camera)
8770                                 goto error;
8771                 }
8772
8773                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8774                 {
8775                         if (!p->texture_reflection)
8776                                 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);
8777                         if (!p->texture_reflection)
8778                                 goto error;
8779                 }
8780         }
8781
8782         // render views
8783         r_refdef.view = originalview;
8784         r_refdef.view.showdebug = false;
8785         r_refdef.view.width = r_waterstate.waterwidth;
8786         r_refdef.view.height = r_waterstate.waterheight;
8787         r_refdef.view.useclipplane = true;
8788         myview = r_refdef.view;
8789         r_waterstate.renderingscene = true;
8790         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8791         {
8792                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8793                 {
8794                         r_refdef.view = myview;
8795                         if(r_water_scissormode.integer)
8796                         {
8797                                 R_SetupView(true);
8798                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8799                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8800                         }
8801
8802                         // render reflected scene and copy into texture
8803                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8804                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8805                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8806                         r_refdef.view.clipplane = p->plane;
8807
8808                         // reverse the cullface settings for this render
8809                         r_refdef.view.cullface_front = GL_FRONT;
8810                         r_refdef.view.cullface_back = GL_BACK;
8811                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8812                         {
8813                                 r_refdef.view.usecustompvs = true;
8814                                 if (p->pvsvalid)
8815                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8816                                 else
8817                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8818                         }
8819
8820                         R_ResetViewRendering3D();
8821                         R_ClearScreen(r_refdef.fogenabled);
8822                         if(r_water_scissormode.integer & 2)
8823                                 R_View_UpdateWithScissor(myscissor);
8824                         else
8825                                 R_View_Update();
8826                         if(r_water_scissormode.integer & 1)
8827                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8828                         R_RenderScene();
8829
8830                         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);
8831                 }
8832
8833                 // render the normal view scene and copy into texture
8834                 // (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)
8835                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8836                 {
8837                         r_refdef.view = myview;
8838                         if(r_water_scissormode.integer)
8839                         {
8840                                 R_SetupView(true);
8841                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8842                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8843                         }
8844
8845                         r_waterstate.renderingrefraction = true;
8846
8847                         r_refdef.view.clipplane = p->plane;
8848                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8849                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8850
8851                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8852                         {
8853                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8854                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8855                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8856                                 R_RenderView_UpdateViewVectors();
8857                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8858                                 {
8859                                         r_refdef.view.usecustompvs = true;
8860                                         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);
8861                                 }
8862                         }
8863
8864                         PlaneClassify(&r_refdef.view.clipplane);
8865
8866                         R_ResetViewRendering3D();
8867                         R_ClearScreen(r_refdef.fogenabled);
8868                         if(r_water_scissormode.integer & 2)
8869                                 R_View_UpdateWithScissor(myscissor);
8870                         else
8871                                 R_View_Update();
8872                         if(r_water_scissormode.integer & 1)
8873                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8874                         R_RenderScene();
8875
8876                         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);
8877                         r_waterstate.renderingrefraction = false;
8878                 }
8879                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8880                 {
8881                         r_refdef.view = myview;
8882
8883                         r_refdef.view.clipplane = p->plane;
8884                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8885                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8886
8887                         r_refdef.view.width = r_waterstate.camerawidth;
8888                         r_refdef.view.height = r_waterstate.cameraheight;
8889                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8890                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8891
8892                         if(p->camera_entity)
8893                         {
8894                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8895                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8896                         }
8897
8898                         // note: all of the view is used for displaying... so
8899                         // there is no use in scissoring
8900
8901                         // reverse the cullface settings for this render
8902                         r_refdef.view.cullface_front = GL_FRONT;
8903                         r_refdef.view.cullface_back = GL_BACK;
8904                         // also reverse the view matrix
8905                         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
8906                         R_RenderView_UpdateViewVectors();
8907                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8908                         {
8909                                 r_refdef.view.usecustompvs = true;
8910                                 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);
8911                         }
8912                         
8913                         // camera needs no clipplane
8914                         r_refdef.view.useclipplane = false;
8915
8916                         PlaneClassify(&r_refdef.view.clipplane);
8917
8918                         R_ResetViewRendering3D();
8919                         R_ClearScreen(r_refdef.fogenabled);
8920                         R_View_Update();
8921                         R_RenderScene();
8922
8923                         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);
8924                         r_waterstate.renderingrefraction = false;
8925                 }
8926
8927         }
8928         r_waterstate.renderingscene = false;
8929         r_refdef.view = originalview;
8930         R_ResetViewRendering3D();
8931         R_ClearScreen(r_refdef.fogenabled);
8932         R_View_Update();
8933         return;
8934 error:
8935         r_refdef.view = originalview;
8936         r_waterstate.renderingscene = false;
8937         Cvar_SetValueQuick(&r_water, 0);
8938         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8939         return;
8940 }
8941
8942 void R_Bloom_StartFrame(void)
8943 {
8944         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8945
8946         switch(vid.renderpath)
8947         {
8948         case RENDERPATH_GL20:
8949         case RENDERPATH_CGGL:
8950         case RENDERPATH_D3D9:
8951         case RENDERPATH_D3D10:
8952         case RENDERPATH_D3D11:
8953                 break;
8954         case RENDERPATH_GL13:
8955         case RENDERPATH_GL11:
8956                 return;
8957         }
8958
8959         // set bloomwidth and bloomheight to the bloom resolution that will be
8960         // used (often less than the screen resolution for faster rendering)
8961         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8962         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8963         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8964         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8965         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8966
8967         // calculate desired texture sizes
8968         if (vid.support.arb_texture_non_power_of_two)
8969         {
8970                 screentexturewidth = r_refdef.view.width;
8971                 screentextureheight = r_refdef.view.height;
8972                 bloomtexturewidth = r_bloomstate.bloomwidth;
8973                 bloomtextureheight = r_bloomstate.bloomheight;
8974         }
8975         else
8976         {
8977                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8978                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8979                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8980                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8981         }
8982
8983         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))
8984         {
8985                 Cvar_SetValueQuick(&r_hdr, 0);
8986                 Cvar_SetValueQuick(&r_bloom, 0);
8987                 Cvar_SetValueQuick(&r_motionblur, 0);
8988                 Cvar_SetValueQuick(&r_damageblur, 0);
8989         }
8990
8991         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)))
8992                 screentexturewidth = screentextureheight = 0;
8993         if (!r_hdr.integer && !r_bloom.integer)
8994                 bloomtexturewidth = bloomtextureheight = 0;
8995
8996         // allocate textures as needed
8997         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8998         {
8999                 if (r_bloomstate.texture_screen)
9000                         R_FreeTexture(r_bloomstate.texture_screen);
9001                 r_bloomstate.texture_screen = NULL;
9002                 r_bloomstate.screentexturewidth = screentexturewidth;
9003                 r_bloomstate.screentextureheight = screentextureheight;
9004                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9005                         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);
9006         }
9007         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9008         {
9009                 if (r_bloomstate.texture_bloom)
9010                         R_FreeTexture(r_bloomstate.texture_bloom);
9011                 r_bloomstate.texture_bloom = NULL;
9012                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9013                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9014                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9015                         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);
9016         }
9017
9018         // when doing a reduced render (HDR) we want to use a smaller area
9019         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9020         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9021         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9022         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9023         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9024
9025         // set up a texcoord array for the full resolution screen image
9026         // (we have to keep this around to copy back during final render)
9027         r_bloomstate.screentexcoord2f[0] = 0;
9028         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9029         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9030         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9031         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9032         r_bloomstate.screentexcoord2f[5] = 0;
9033         r_bloomstate.screentexcoord2f[6] = 0;
9034         r_bloomstate.screentexcoord2f[7] = 0;
9035
9036         // set up a texcoord array for the reduced resolution bloom image
9037         // (which will be additive blended over the screen image)
9038         r_bloomstate.bloomtexcoord2f[0] = 0;
9039         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9040         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9041         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9042         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9043         r_bloomstate.bloomtexcoord2f[5] = 0;
9044         r_bloomstate.bloomtexcoord2f[6] = 0;
9045         r_bloomstate.bloomtexcoord2f[7] = 0;
9046
9047         switch(vid.renderpath)
9048         {
9049         case RENDERPATH_GL11:
9050         case RENDERPATH_GL13:
9051         case RENDERPATH_GL20:
9052         case RENDERPATH_CGGL:
9053                 break;
9054         case RENDERPATH_D3D9:
9055         case RENDERPATH_D3D10:
9056         case RENDERPATH_D3D11:
9057                 {
9058                         int i;
9059                         for (i = 0;i < 4;i++)
9060                         {
9061                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9062                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9063                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9064                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9065                         }
9066                 }
9067                 break;
9068         }
9069
9070         if (r_hdr.integer || r_bloom.integer)
9071         {
9072                 r_bloomstate.enabled = true;
9073                 r_bloomstate.hdr = r_hdr.integer != 0;
9074         }
9075
9076         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);
9077 }
9078
9079 void R_Bloom_CopyBloomTexture(float colorscale)
9080 {
9081         r_refdef.stats.bloom++;
9082
9083         // scale down screen texture to the bloom texture size
9084         CHECKGLERROR
9085         R_SetViewport(&r_bloomstate.viewport);
9086         GL_BlendFunc(GL_ONE, GL_ZERO);
9087         GL_Color(colorscale, colorscale, colorscale, 1);
9088         // 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...
9089         switch(vid.renderpath)
9090         {
9091         case RENDERPATH_GL11:
9092         case RENDERPATH_GL13:
9093         case RENDERPATH_GL20:
9094         case RENDERPATH_CGGL:
9095                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9096                 break;
9097         case RENDERPATH_D3D9:
9098         case RENDERPATH_D3D10:
9099         case RENDERPATH_D3D11:
9100                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9101                 break;
9102         }
9103         // TODO: do boxfilter scale-down in shader?
9104         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9105         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9106         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9107
9108         // we now have a bloom image in the framebuffer
9109         // copy it into the bloom image texture for later processing
9110         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);
9111         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9112 }
9113
9114 void R_Bloom_CopyHDRTexture(void)
9115 {
9116         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);
9117         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9118 }
9119
9120 void R_Bloom_MakeTexture(void)
9121 {
9122         int x, range, dir;
9123         float xoffset, yoffset, r, brighten;
9124
9125         r_refdef.stats.bloom++;
9126
9127         R_ResetViewRendering2D();
9128
9129         // we have a bloom image in the framebuffer
9130         CHECKGLERROR
9131         R_SetViewport(&r_bloomstate.viewport);
9132
9133         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9134         {
9135                 x *= 2;
9136                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9137                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9138                 GL_Color(r,r,r,1);
9139                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9140                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9141                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9142                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9143
9144                 // copy the vertically blurred bloom view to a texture
9145                 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);
9146                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9147         }
9148
9149         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9150         brighten = r_bloom_brighten.value;
9151         if (r_hdr.integer)
9152                 brighten *= r_hdr_range.value;
9153         brighten = sqrt(brighten);
9154         if(range >= 1)
9155                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9156         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9157
9158         for (dir = 0;dir < 2;dir++)
9159         {
9160                 // blend on at multiple vertical offsets to achieve a vertical blur
9161                 // TODO: do offset blends using GLSL
9162                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9163                 GL_BlendFunc(GL_ONE, GL_ZERO);
9164                 for (x = -range;x <= range;x++)
9165                 {
9166                         if (!dir){xoffset = 0;yoffset = x;}
9167                         else {xoffset = x;yoffset = 0;}
9168                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9169                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9170                         // compute a texcoord array with the specified x and y offset
9171                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9172                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9173                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9174                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9175                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9176                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9177                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9178                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9179                         // this r value looks like a 'dot' particle, fading sharply to
9180                         // black at the edges
9181                         // (probably not realistic but looks good enough)
9182                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9183                         //r = brighten/(range*2+1);
9184                         r = brighten / (range * 2 + 1);
9185                         if(range >= 1)
9186                                 r *= (1 - x*x/(float)(range*range));
9187                         GL_Color(r, r, r, 1);
9188                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9189                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9190                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9191                         GL_BlendFunc(GL_ONE, GL_ONE);
9192                 }
9193
9194                 // copy the vertically blurred bloom view to a texture
9195                 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);
9196                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9197         }
9198 }
9199
9200 void R_HDR_RenderBloomTexture(void)
9201 {
9202         int oldwidth, oldheight;
9203         float oldcolorscale;
9204         int oldwaterstate;
9205
9206         oldwaterstate = r_waterstate.enabled;
9207         oldcolorscale = r_refdef.view.colorscale;
9208         oldwidth = r_refdef.view.width;
9209         oldheight = r_refdef.view.height;
9210         r_refdef.view.width = r_bloomstate.bloomwidth;
9211         r_refdef.view.height = r_bloomstate.bloomheight;
9212
9213         if(r_hdr.integer < 2)
9214                 r_waterstate.enabled = false;
9215
9216         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9217         // TODO: add exposure compensation features
9218         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9219
9220         r_refdef.view.showdebug = false;
9221         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9222
9223         R_ResetViewRendering3D();
9224
9225         R_ClearScreen(r_refdef.fogenabled);
9226         if (r_timereport_active)
9227                 R_TimeReport("HDRclear");
9228
9229         R_View_Update();
9230         if (r_timereport_active)
9231                 R_TimeReport("visibility");
9232
9233         // only do secondary renders with HDR if r_hdr is 2 or higher
9234         r_waterstate.numwaterplanes = 0;
9235         if (r_waterstate.enabled)
9236                 R_RenderWaterPlanes();
9237
9238         r_refdef.view.showdebug = true;
9239         R_RenderScene();
9240         r_waterstate.numwaterplanes = 0;
9241
9242         R_ResetViewRendering2D();
9243
9244         R_Bloom_CopyHDRTexture();
9245         R_Bloom_MakeTexture();
9246
9247         // restore the view settings
9248         r_waterstate.enabled = oldwaterstate;
9249         r_refdef.view.width = oldwidth;
9250         r_refdef.view.height = oldheight;
9251         r_refdef.view.colorscale = oldcolorscale;
9252
9253         R_ResetViewRendering3D();
9254
9255         R_ClearScreen(r_refdef.fogenabled);
9256         if (r_timereport_active)
9257                 R_TimeReport("viewclear");
9258 }
9259
9260 static void R_BlendView(void)
9261 {
9262         unsigned int permutation;
9263         float uservecs[4][4];
9264
9265         switch (vid.renderpath)
9266         {
9267         case RENDERPATH_GL20:
9268         case RENDERPATH_CGGL:
9269         case RENDERPATH_D3D9:
9270         case RENDERPATH_D3D10:
9271         case RENDERPATH_D3D11:
9272                 permutation =
9273                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9274                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9275                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9276                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9277                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9278
9279                 if (r_bloomstate.texture_screen)
9280                 {
9281                         // make sure the buffer is available
9282                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9283
9284                         R_ResetViewRendering2D();
9285
9286                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9287                         {
9288                                 // declare variables
9289                                 float speed;
9290                                 static float avgspeed;
9291
9292                                 speed = VectorLength(cl.movement_velocity);
9293
9294                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9295                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9296
9297                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9298                                 speed = bound(0, speed, 1);
9299                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9300
9301                                 // calculate values into a standard alpha
9302                                 cl.motionbluralpha = 1 - exp(-
9303                                                 (
9304                                                  (r_motionblur.value * speed / 80)
9305                                                  +
9306                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9307                                                 )
9308                                                 /
9309                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9310                                            );
9311
9312                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9313                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9314                                 // apply the blur
9315                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9316                                 {
9317                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9318                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9319                                         switch(vid.renderpath)
9320                                         {
9321                                         case RENDERPATH_GL11:
9322                                         case RENDERPATH_GL13:
9323                                         case RENDERPATH_GL20:
9324                                         case RENDERPATH_CGGL:
9325                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9326                                                 break;
9327                                         case RENDERPATH_D3D9:
9328                                         case RENDERPATH_D3D10:
9329                                         case RENDERPATH_D3D11:
9330                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9331                                                 break;
9332                                         }
9333                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9334                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9335                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9336                                 }
9337                         }
9338
9339                         // copy view into the screen texture
9340                         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);
9341                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9342                 }
9343                 else if (!r_bloomstate.texture_bloom)
9344                 {
9345                         // we may still have to do view tint...
9346                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9347                         {
9348                                 // apply a color tint to the whole view
9349                                 R_ResetViewRendering2D();
9350                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9351                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9352                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9353                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9354                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9355                         }
9356                         break; // no screen processing, no bloom, skip it
9357                 }
9358
9359                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9360                 {
9361                         // render simple bloom effect
9362                         // copy the screen and shrink it and darken it for the bloom process
9363                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9364                         // make the bloom texture
9365                         R_Bloom_MakeTexture();
9366                 }
9367
9368 #if _MSC_VER >= 1400
9369 #define sscanf sscanf_s
9370 #endif
9371                 memset(uservecs, 0, sizeof(uservecs));
9372                 if (r_glsl_postprocess_uservec1_enable.integer)
9373                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9374                 if (r_glsl_postprocess_uservec2_enable.integer)
9375                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9376                 if (r_glsl_postprocess_uservec3_enable.integer)
9377                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9378                 if (r_glsl_postprocess_uservec4_enable.integer)
9379                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9380
9381                 R_ResetViewRendering2D();
9382                 GL_Color(1, 1, 1, 1);
9383                 GL_BlendFunc(GL_ONE, GL_ZERO);
9384
9385                 switch(vid.renderpath)
9386                 {
9387                 case RENDERPATH_GL20:
9388                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9389                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9390                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9391                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9392                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9393                         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]);
9394                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9395                         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]);
9396                         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]);
9397                         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]);
9398                         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]);
9399                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9400                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9401                         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);
9402                         break;
9403                 case RENDERPATH_CGGL:
9404 #ifdef SUPPORTCG
9405                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9406                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9407                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9408                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9409                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9410                         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
9411                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9412                         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
9413                         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
9414                         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
9415                         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
9416                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9417                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9418                         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);
9419 #endif
9420                         break;
9421                 case RENDERPATH_D3D9:
9422 #ifdef SUPPORTD3D
9423                         // 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...
9424                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9425                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9426                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9427                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9428                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9429                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9430                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9431                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9432                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9433                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9434                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9435                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9436                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9437                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9438 #endif
9439                         break;
9440                 case RENDERPATH_D3D10:
9441                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9442                         break;
9443                 case RENDERPATH_D3D11:
9444                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9445                         break;
9446                 default:
9447                         break;
9448                 }
9449                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9450                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9451                 break;
9452         case RENDERPATH_GL13:
9453         case RENDERPATH_GL11:
9454                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9455                 {
9456                         // apply a color tint to the whole view
9457                         R_ResetViewRendering2D();
9458                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9459                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9460                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9461                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9462                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9463                 }
9464                 break;
9465         }
9466 }
9467
9468 matrix4x4_t r_waterscrollmatrix;
9469
9470 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9471 {
9472         if (r_refdef.fog_density)
9473         {
9474                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9475                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9476                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9477
9478                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9479                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9480                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9481                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9482
9483                 {
9484                         vec3_t fogvec;
9485                         VectorCopy(r_refdef.fogcolor, fogvec);
9486                         //   color.rgb *= ContrastBoost * SceneBrightness;
9487                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9488                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9489                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9490                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9491                 }
9492         }
9493 }
9494
9495 void R_UpdateVariables(void)
9496 {
9497         R_Textures_Frame();
9498
9499         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9500
9501         r_refdef.farclip = r_farclip_base.value;
9502         if (r_refdef.scene.worldmodel)
9503                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9504         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9505
9506         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9507                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9508         r_refdef.polygonfactor = 0;
9509         r_refdef.polygonoffset = 0;
9510         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9511         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9512
9513         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9514         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9515         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9516         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9517         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9518         if (FAKELIGHT_ENABLED)
9519         {
9520                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9521         }
9522         if (r_showsurfaces.integer)
9523         {
9524                 r_refdef.scene.rtworld = false;
9525                 r_refdef.scene.rtworldshadows = false;
9526                 r_refdef.scene.rtdlight = false;
9527                 r_refdef.scene.rtdlightshadows = false;
9528                 r_refdef.lightmapintensity = 0;
9529         }
9530
9531         if (gamemode == GAME_NEHAHRA)
9532         {
9533                 if (gl_fogenable.integer)
9534                 {
9535                         r_refdef.oldgl_fogenable = true;
9536                         r_refdef.fog_density = gl_fogdensity.value;
9537                         r_refdef.fog_red = gl_fogred.value;
9538                         r_refdef.fog_green = gl_foggreen.value;
9539                         r_refdef.fog_blue = gl_fogblue.value;
9540                         r_refdef.fog_alpha = 1;
9541                         r_refdef.fog_start = 0;
9542                         r_refdef.fog_end = gl_skyclip.value;
9543                         r_refdef.fog_height = 1<<30;
9544                         r_refdef.fog_fadedepth = 128;
9545                 }
9546                 else if (r_refdef.oldgl_fogenable)
9547                 {
9548                         r_refdef.oldgl_fogenable = false;
9549                         r_refdef.fog_density = 0;
9550                         r_refdef.fog_red = 0;
9551                         r_refdef.fog_green = 0;
9552                         r_refdef.fog_blue = 0;
9553                         r_refdef.fog_alpha = 0;
9554                         r_refdef.fog_start = 0;
9555                         r_refdef.fog_end = 0;
9556                         r_refdef.fog_height = 1<<30;
9557                         r_refdef.fog_fadedepth = 128;
9558                 }
9559         }
9560
9561         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9562         r_refdef.fog_start = max(0, r_refdef.fog_start);
9563         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9564
9565         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9566
9567         if (r_refdef.fog_density && r_drawfog.integer)
9568         {
9569                 r_refdef.fogenabled = true;
9570                 // this is the point where the fog reaches 0.9986 alpha, which we
9571                 // consider a good enough cutoff point for the texture
9572                 // (0.9986 * 256 == 255.6)
9573                 if (r_fog_exp2.integer)
9574                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9575                 else
9576                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9577                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9578                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9579                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9580                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9581                         R_BuildFogHeightTexture();
9582                 // fog color was already set
9583                 // update the fog texture
9584                 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)
9585                         R_BuildFogTexture();
9586                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9587                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9588         }
9589         else
9590                 r_refdef.fogenabled = false;
9591
9592         switch(vid.renderpath)
9593         {
9594         case RENDERPATH_GL20:
9595         case RENDERPATH_CGGL:
9596         case RENDERPATH_D3D9:
9597         case RENDERPATH_D3D10:
9598         case RENDERPATH_D3D11:
9599                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9600                 {
9601                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9602                         {
9603                                 // build GLSL gamma texture
9604 #define RAMPWIDTH 256
9605                                 unsigned short ramp[RAMPWIDTH * 3];
9606                                 unsigned char rampbgr[RAMPWIDTH][4];
9607                                 int i;
9608
9609                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9610
9611                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9612                                 for(i = 0; i < RAMPWIDTH; ++i)
9613                                 {
9614                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9615                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9616                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9617                                         rampbgr[i][3] = 0;
9618                                 }
9619                                 if (r_texture_gammaramps)
9620                                 {
9621                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9622                                 }
9623                                 else
9624                                 {
9625                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9626                                 }
9627                         }
9628                 }
9629                 else
9630                 {
9631                         // remove GLSL gamma texture
9632                 }
9633                 break;
9634         case RENDERPATH_GL13:
9635         case RENDERPATH_GL11:
9636                 break;
9637         }
9638 }
9639
9640 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9641 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9642 /*
9643 ================
9644 R_SelectScene
9645 ================
9646 */
9647 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9648         if( scenetype != r_currentscenetype ) {
9649                 // store the old scenetype
9650                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9651                 r_currentscenetype = scenetype;
9652                 // move in the new scene
9653                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9654         }
9655 }
9656
9657 /*
9658 ================
9659 R_GetScenePointer
9660 ================
9661 */
9662 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9663 {
9664         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9665         if( scenetype == r_currentscenetype ) {
9666                 return &r_refdef.scene;
9667         } else {
9668                 return &r_scenes_store[ scenetype ];
9669         }
9670 }
9671
9672 /*
9673 ================
9674 R_RenderView
9675 ================
9676 */
9677 void R_RenderView(void)
9678 {
9679         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9680         if (r_timereport_active)
9681                 R_TimeReport("start");
9682         r_textureframe++; // used only by R_GetCurrentTexture
9683         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9684
9685         if(R_CompileShader_CheckStaticParms())
9686                 R_GLSL_Restart_f();
9687
9688         if (!r_drawentities.integer)
9689                 r_refdef.scene.numentities = 0;
9690
9691         R_AnimCache_ClearCache();
9692         R_FrameData_NewFrame();
9693
9694         /* adjust for stereo display */
9695         if(R_Stereo_Active())
9696         {
9697                 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);
9698                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9699         }
9700
9701         if (r_refdef.view.isoverlay)
9702         {
9703                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9704                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9705                 R_TimeReport("depthclear");
9706
9707                 r_refdef.view.showdebug = false;
9708
9709                 r_waterstate.enabled = false;
9710                 r_waterstate.numwaterplanes = 0;
9711
9712                 R_RenderScene();
9713
9714                 r_refdef.view.matrix = originalmatrix;
9715
9716                 CHECKGLERROR
9717                 return;
9718         }
9719
9720         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9721         {
9722                 r_refdef.view.matrix = originalmatrix;
9723                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9724         }
9725
9726         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9727
9728         R_RenderView_UpdateViewVectors();
9729
9730         R_Shadow_UpdateWorldLightSelection();
9731
9732         R_Bloom_StartFrame();
9733         R_Water_StartFrame();
9734
9735         CHECKGLERROR
9736         if (r_timereport_active)
9737                 R_TimeReport("viewsetup");
9738
9739         R_ResetViewRendering3D();
9740
9741         if (r_refdef.view.clear || r_refdef.fogenabled)
9742         {
9743                 R_ClearScreen(r_refdef.fogenabled);
9744                 if (r_timereport_active)
9745                         R_TimeReport("viewclear");
9746         }
9747         r_refdef.view.clear = true;
9748
9749         // this produces a bloom texture to be used in R_BlendView() later
9750         if (r_hdr.integer && r_bloomstate.bloomwidth)
9751         {
9752                 R_HDR_RenderBloomTexture();
9753                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9754                 r_textureframe++; // used only by R_GetCurrentTexture
9755         }
9756
9757         r_refdef.view.showdebug = true;
9758
9759         R_View_Update();
9760         if (r_timereport_active)
9761                 R_TimeReport("visibility");
9762
9763         r_waterstate.numwaterplanes = 0;
9764         if (r_waterstate.enabled)
9765                 R_RenderWaterPlanes();
9766
9767         R_RenderScene();
9768         r_waterstate.numwaterplanes = 0;
9769
9770         R_BlendView();
9771         if (r_timereport_active)
9772                 R_TimeReport("blendview");
9773
9774         GL_Scissor(0, 0, vid.width, vid.height);
9775         GL_ScissorTest(false);
9776
9777         r_refdef.view.matrix = originalmatrix;
9778
9779         CHECKGLERROR
9780 }
9781
9782 void R_RenderWaterPlanes(void)
9783 {
9784         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9785         {
9786                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9787                 if (r_timereport_active)
9788                         R_TimeReport("waterworld");
9789         }
9790
9791         // don't let sound skip if going slow
9792         if (r_refdef.scene.extraupdate)
9793                 S_ExtraUpdate ();
9794
9795         R_DrawModelsAddWaterPlanes();
9796         if (r_timereport_active)
9797                 R_TimeReport("watermodels");
9798
9799         if (r_waterstate.numwaterplanes)
9800         {
9801                 R_Water_ProcessPlanes();
9802                 if (r_timereport_active)
9803                         R_TimeReport("waterscenes");
9804         }
9805 }
9806
9807 extern void R_DrawLightningBeams (void);
9808 extern void VM_CL_AddPolygonsToMeshQueue (void);
9809 extern void R_DrawPortals (void);
9810 extern cvar_t cl_locs_show;
9811 static void R_DrawLocs(void);
9812 static void R_DrawEntityBBoxes(void);
9813 static void R_DrawModelDecals(void);
9814 extern void R_DrawModelShadows(void);
9815 extern void R_DrawModelShadowMaps(void);
9816 extern cvar_t cl_decals_newsystem;
9817 extern qboolean r_shadow_usingdeferredprepass;
9818 void R_RenderScene(void)
9819 {
9820         qboolean shadowmapping = false;
9821
9822         if (r_timereport_active)
9823                 R_TimeReport("beginscene");
9824
9825         r_refdef.stats.renders++;
9826
9827         R_UpdateFogColor();
9828
9829         // don't let sound skip if going slow
9830         if (r_refdef.scene.extraupdate)
9831                 S_ExtraUpdate ();
9832
9833         R_MeshQueue_BeginScene();
9834
9835         R_SkyStartFrame();
9836
9837         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);
9838
9839         if (r_timereport_active)
9840                 R_TimeReport("skystartframe");
9841
9842         if (cl.csqc_vidvars.drawworld)
9843         {
9844                 // don't let sound skip if going slow
9845                 if (r_refdef.scene.extraupdate)
9846                         S_ExtraUpdate ();
9847
9848                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9849                 {
9850                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9851                         if (r_timereport_active)
9852                                 R_TimeReport("worldsky");
9853                 }
9854
9855                 if (R_DrawBrushModelsSky() && r_timereport_active)
9856                         R_TimeReport("bmodelsky");
9857
9858                 if (skyrendermasked && skyrenderlater)
9859                 {
9860                         // we have to force off the water clipping plane while rendering sky
9861                         R_SetupView(false);
9862                         R_Sky();
9863                         R_SetupView(true);
9864                         if (r_timereport_active)
9865                                 R_TimeReport("sky");
9866                 }
9867         }
9868
9869         R_AnimCache_CacheVisibleEntities();
9870         if (r_timereport_active)
9871                 R_TimeReport("animation");
9872
9873         R_Shadow_PrepareLights();
9874         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9875                 R_Shadow_PrepareModelShadows();
9876         if (r_timereport_active)
9877                 R_TimeReport("preparelights");
9878
9879         if (R_Shadow_ShadowMappingEnabled())
9880                 shadowmapping = true;
9881
9882         if (r_shadow_usingdeferredprepass)
9883                 R_Shadow_DrawPrepass();
9884
9885         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9886         {
9887                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9888                 if (r_timereport_active)
9889                         R_TimeReport("worlddepth");
9890         }
9891         if (r_depthfirst.integer >= 2)
9892         {
9893                 R_DrawModelsDepth();
9894                 if (r_timereport_active)
9895                         R_TimeReport("modeldepth");
9896         }
9897
9898         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9899         {
9900                 R_DrawModelShadowMaps();
9901                 R_ResetViewRendering3D();
9902                 // don't let sound skip if going slow
9903                 if (r_refdef.scene.extraupdate)
9904                         S_ExtraUpdate ();
9905         }
9906
9907         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9908         {
9909                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9910                 if (r_timereport_active)
9911                         R_TimeReport("world");
9912         }
9913
9914         // don't let sound skip if going slow
9915         if (r_refdef.scene.extraupdate)
9916                 S_ExtraUpdate ();
9917
9918         R_DrawModels();
9919         if (r_timereport_active)
9920                 R_TimeReport("models");
9921
9922         // don't let sound skip if going slow
9923         if (r_refdef.scene.extraupdate)
9924                 S_ExtraUpdate ();
9925
9926         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9927         {
9928                 R_DrawModelShadows();
9929                 R_ResetViewRendering3D();
9930                 // don't let sound skip if going slow
9931                 if (r_refdef.scene.extraupdate)
9932                         S_ExtraUpdate ();
9933         }
9934
9935         if (!r_shadow_usingdeferredprepass)
9936         {
9937                 R_Shadow_DrawLights();
9938                 if (r_timereport_active)
9939                         R_TimeReport("rtlights");
9940         }
9941
9942         // don't let sound skip if going slow
9943         if (r_refdef.scene.extraupdate)
9944                 S_ExtraUpdate ();
9945
9946         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9947         {
9948                 R_DrawModelShadows();
9949                 R_ResetViewRendering3D();
9950                 // don't let sound skip if going slow
9951                 if (r_refdef.scene.extraupdate)
9952                         S_ExtraUpdate ();
9953         }
9954
9955         if (cl.csqc_vidvars.drawworld)
9956         {
9957                 if (cl_decals_newsystem.integer)
9958                 {
9959                         R_DrawModelDecals();
9960                         if (r_timereport_active)
9961                                 R_TimeReport("modeldecals");
9962                 }
9963                 else
9964                 {
9965                         R_DrawDecals();
9966                         if (r_timereport_active)
9967                                 R_TimeReport("decals");
9968                 }
9969
9970                 R_DrawParticles();
9971                 if (r_timereport_active)
9972                         R_TimeReport("particles");
9973
9974                 R_DrawExplosions();
9975                 if (r_timereport_active)
9976                         R_TimeReport("explosions");
9977
9978                 R_DrawLightningBeams();
9979                 if (r_timereport_active)
9980                         R_TimeReport("lightning");
9981         }
9982
9983         VM_CL_AddPolygonsToMeshQueue();
9984
9985         if (r_refdef.view.showdebug)
9986         {
9987                 if (cl_locs_show.integer)
9988                 {
9989                         R_DrawLocs();
9990                         if (r_timereport_active)
9991                                 R_TimeReport("showlocs");
9992                 }
9993
9994                 if (r_drawportals.integer)
9995                 {
9996                         R_DrawPortals();
9997                         if (r_timereport_active)
9998                                 R_TimeReport("portals");
9999                 }
10000
10001                 if (r_showbboxes.value > 0)
10002                 {
10003                         R_DrawEntityBBoxes();
10004                         if (r_timereport_active)
10005                                 R_TimeReport("bboxes");
10006                 }
10007         }
10008
10009         R_MeshQueue_RenderTransparent();
10010         if (r_timereport_active)
10011                 R_TimeReport("drawtrans");
10012
10013         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))
10014         {
10015                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10016                 if (r_timereport_active)
10017                         R_TimeReport("worlddebug");
10018                 R_DrawModelsDebug();
10019                 if (r_timereport_active)
10020                         R_TimeReport("modeldebug");
10021         }
10022
10023         if (cl.csqc_vidvars.drawworld)
10024         {
10025                 R_Shadow_DrawCoronas();
10026                 if (r_timereport_active)
10027                         R_TimeReport("coronas");
10028         }
10029
10030 #if 0
10031         {
10032                 GL_DepthTest(false);
10033                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10034                 GL_Color(1, 1, 1, 1);
10035                 qglBegin(GL_POLYGON);
10036                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10037                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10038                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10039                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10040                 qglEnd();
10041                 qglBegin(GL_POLYGON);
10042                 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]);
10043                 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]);
10044                 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]);
10045                 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]);
10046                 qglEnd();
10047                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10048         }
10049 #endif
10050
10051         // don't let sound skip if going slow
10052         if (r_refdef.scene.extraupdate)
10053                 S_ExtraUpdate ();
10054
10055         R_ResetViewRendering2D();
10056 }
10057
10058 static const unsigned short bboxelements[36] =
10059 {
10060         5, 1, 3, 5, 3, 7,
10061         6, 2, 0, 6, 0, 4,
10062         7, 3, 2, 7, 2, 6,
10063         4, 0, 1, 4, 1, 5,
10064         4, 5, 7, 4, 7, 6,
10065         1, 0, 2, 1, 2, 3,
10066 };
10067
10068 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10069 {
10070         int i;
10071         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10072
10073         RSurf_ActiveWorldEntity();
10074
10075         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10076         GL_DepthMask(false);
10077         GL_DepthRange(0, 1);
10078         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10079 //      R_Mesh_ResetTextureState();
10080
10081         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10082         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10083         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10084         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10085         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10086         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10087         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10088         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10089         R_FillColors(color4f, 8, cr, cg, cb, ca);
10090         if (r_refdef.fogenabled)
10091         {
10092                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10093                 {
10094                         f1 = RSurf_FogVertex(v);
10095                         f2 = 1 - f1;
10096                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10097                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10098                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10099                 }
10100         }
10101         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10102         R_Mesh_ResetTextureState();
10103         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10104         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10105 }
10106
10107 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10108 {
10109         int i;
10110         float color[4];
10111         prvm_edict_t *edict;
10112         prvm_prog_t *prog_save = prog;
10113
10114         // this function draws bounding boxes of server entities
10115         if (!sv.active)
10116                 return;
10117
10118         GL_CullFace(GL_NONE);
10119         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10120
10121         prog = 0;
10122         SV_VM_Begin();
10123         for (i = 0;i < numsurfaces;i++)
10124         {
10125                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10126                 switch ((int)edict->fields.server->solid)
10127                 {
10128                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10129                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10130                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10131                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10132                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10133                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10134                 }
10135                 color[3] *= r_showbboxes.value;
10136                 color[3] = bound(0, color[3], 1);
10137                 GL_DepthTest(!r_showdisabledepthtest.integer);
10138                 GL_CullFace(r_refdef.view.cullface_front);
10139                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10140         }
10141         SV_VM_End();
10142         prog = prog_save;
10143 }
10144
10145 static void R_DrawEntityBBoxes(void)
10146 {
10147         int i;
10148         prvm_edict_t *edict;
10149         vec3_t center;
10150         prvm_prog_t *prog_save = prog;
10151
10152         // this function draws bounding boxes of server entities
10153         if (!sv.active)
10154                 return;
10155
10156         prog = 0;
10157         SV_VM_Begin();
10158         for (i = 0;i < prog->num_edicts;i++)
10159         {
10160                 edict = PRVM_EDICT_NUM(i);
10161                 if (edict->priv.server->free)
10162                         continue;
10163                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10164                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10165                         continue;
10166                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10167                         continue;
10168                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10169                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10170         }
10171         SV_VM_End();
10172         prog = prog_save;
10173 }
10174
10175 static const int nomodelelement3i[24] =
10176 {
10177         5, 2, 0,
10178         5, 1, 2,
10179         5, 0, 3,
10180         5, 3, 1,
10181         0, 2, 4,
10182         2, 1, 4,
10183         3, 0, 4,
10184         1, 3, 4
10185 };
10186
10187 static const unsigned short nomodelelement3s[24] =
10188 {
10189         5, 2, 0,
10190         5, 1, 2,
10191         5, 0, 3,
10192         5, 3, 1,
10193         0, 2, 4,
10194         2, 1, 4,
10195         3, 0, 4,
10196         1, 3, 4
10197 };
10198
10199 static const float nomodelvertex3f[6*3] =
10200 {
10201         -16,   0,   0,
10202          16,   0,   0,
10203           0, -16,   0,
10204           0,  16,   0,
10205           0,   0, -16,
10206           0,   0,  16
10207 };
10208
10209 static const float nomodelcolor4f[6*4] =
10210 {
10211         0.0f, 0.0f, 0.5f, 1.0f,
10212         0.0f, 0.0f, 0.5f, 1.0f,
10213         0.0f, 0.5f, 0.0f, 1.0f,
10214         0.0f, 0.5f, 0.0f, 1.0f,
10215         0.5f, 0.0f, 0.0f, 1.0f,
10216         0.5f, 0.0f, 0.0f, 1.0f
10217 };
10218
10219 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10220 {
10221         int i;
10222         float f1, f2, *c;
10223         float color4f[6*4];
10224
10225         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);
10226
10227         // this is only called once per entity so numsurfaces is always 1, and
10228         // surfacelist is always {0}, so this code does not handle batches
10229
10230         if (rsurface.ent_flags & RENDER_ADDITIVE)
10231         {
10232                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10233                 GL_DepthMask(false);
10234         }
10235         else if (rsurface.colormod[3] < 1)
10236         {
10237                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10238                 GL_DepthMask(false);
10239         }
10240         else
10241         {
10242                 GL_BlendFunc(GL_ONE, GL_ZERO);
10243                 GL_DepthMask(true);
10244         }
10245         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10246         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10247         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10248         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10249         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10250         for (i = 0, c = color4f;i < 6;i++, c += 4)
10251         {
10252                 c[0] *= rsurface.colormod[0];
10253                 c[1] *= rsurface.colormod[1];
10254                 c[2] *= rsurface.colormod[2];
10255                 c[3] *= rsurface.colormod[3];
10256         }
10257         if (r_refdef.fogenabled)
10258         {
10259                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10260                 {
10261                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10262                         f2 = 1 - f1;
10263                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10264                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10265                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10266                 }
10267         }
10268 //      R_Mesh_ResetTextureState();
10269         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10270         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10271         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10272 }
10273
10274 void R_DrawNoModel(entity_render_t *ent)
10275 {
10276         vec3_t org;
10277         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10278         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10279                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10280         else
10281                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10282 }
10283
10284 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10285 {
10286         vec3_t right1, right2, diff, normal;
10287
10288         VectorSubtract (org2, org1, normal);
10289
10290         // calculate 'right' vector for start
10291         VectorSubtract (r_refdef.view.origin, org1, diff);
10292         CrossProduct (normal, diff, right1);
10293         VectorNormalize (right1);
10294
10295         // calculate 'right' vector for end
10296         VectorSubtract (r_refdef.view.origin, org2, diff);
10297         CrossProduct (normal, diff, right2);
10298         VectorNormalize (right2);
10299
10300         vert[ 0] = org1[0] + width * right1[0];
10301         vert[ 1] = org1[1] + width * right1[1];
10302         vert[ 2] = org1[2] + width * right1[2];
10303         vert[ 3] = org1[0] - width * right1[0];
10304         vert[ 4] = org1[1] - width * right1[1];
10305         vert[ 5] = org1[2] - width * right1[2];
10306         vert[ 6] = org2[0] - width * right2[0];
10307         vert[ 7] = org2[1] - width * right2[1];
10308         vert[ 8] = org2[2] - width * right2[2];
10309         vert[ 9] = org2[0] + width * right2[0];
10310         vert[10] = org2[1] + width * right2[1];
10311         vert[11] = org2[2] + width * right2[2];
10312 }
10313
10314 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)
10315 {
10316         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10317         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10318         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10319         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10320         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10321         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10322         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10323         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10324         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10325         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10326         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10327         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10328 }
10329
10330 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10331 {
10332         int i;
10333         float *vertex3f;
10334         float v[3];
10335         VectorSet(v, x, y, z);
10336         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10337                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10338                         break;
10339         if (i == mesh->numvertices)
10340         {
10341                 if (mesh->numvertices < mesh->maxvertices)
10342                 {
10343                         VectorCopy(v, vertex3f);
10344                         mesh->numvertices++;
10345                 }
10346                 return mesh->numvertices;
10347         }
10348         else
10349                 return i;
10350 }
10351
10352 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10353 {
10354         int i;
10355         int *e, element[3];
10356         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10357         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10358         e = mesh->element3i + mesh->numtriangles * 3;
10359         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10360         {
10361                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10362                 if (mesh->numtriangles < mesh->maxtriangles)
10363                 {
10364                         *e++ = element[0];
10365                         *e++ = element[1];
10366                         *e++ = element[2];
10367                         mesh->numtriangles++;
10368                 }
10369                 element[1] = element[2];
10370         }
10371 }
10372
10373 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10374 {
10375         int i;
10376         int *e, element[3];
10377         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10378         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10379         e = mesh->element3i + mesh->numtriangles * 3;
10380         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10381         {
10382                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10383                 if (mesh->numtriangles < mesh->maxtriangles)
10384                 {
10385                         *e++ = element[0];
10386                         *e++ = element[1];
10387                         *e++ = element[2];
10388                         mesh->numtriangles++;
10389                 }
10390                 element[1] = element[2];
10391         }
10392 }
10393
10394 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10395 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10396 {
10397         int planenum, planenum2;
10398         int w;
10399         int tempnumpoints;
10400         mplane_t *plane, *plane2;
10401         double maxdist;
10402         double temppoints[2][256*3];
10403         // figure out how large a bounding box we need to properly compute this brush
10404         maxdist = 0;
10405         for (w = 0;w < numplanes;w++)
10406                 maxdist = max(maxdist, fabs(planes[w].dist));
10407         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10408         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10409         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10410         {
10411                 w = 0;
10412                 tempnumpoints = 4;
10413                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10414                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10415                 {
10416                         if (planenum2 == planenum)
10417                                 continue;
10418                         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);
10419                         w = !w;
10420                 }
10421                 if (tempnumpoints < 3)
10422                         continue;
10423                 // generate elements forming a triangle fan for this polygon
10424                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10425         }
10426 }
10427
10428 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)
10429 {
10430         texturelayer_t *layer;
10431         layer = t->currentlayers + t->currentnumlayers++;
10432         layer->type = type;
10433         layer->depthmask = depthmask;
10434         layer->blendfunc1 = blendfunc1;
10435         layer->blendfunc2 = blendfunc2;
10436         layer->texture = texture;
10437         layer->texmatrix = *matrix;
10438         layer->color[0] = r;
10439         layer->color[1] = g;
10440         layer->color[2] = b;
10441         layer->color[3] = a;
10442 }
10443
10444 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10445 {
10446         if(parms[0] == 0 && parms[1] == 0)
10447                 return false;
10448         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10449                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10450                         return false;
10451         return true;
10452 }
10453
10454 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10455 {
10456         double index, f;
10457         index = parms[2] + r_refdef.scene.time * parms[3];
10458         index -= floor(index);
10459         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10460         {
10461         default:
10462         case Q3WAVEFUNC_NONE:
10463         case Q3WAVEFUNC_NOISE:
10464         case Q3WAVEFUNC_COUNT:
10465                 f = 0;
10466                 break;
10467         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10468         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10469         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10470         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10471         case Q3WAVEFUNC_TRIANGLE:
10472                 index *= 4;
10473                 f = index - floor(index);
10474                 if (index < 1)
10475                         f = f;
10476                 else if (index < 2)
10477                         f = 1 - f;
10478                 else if (index < 3)
10479                         f = -f;
10480                 else
10481                         f = -(1 - f);
10482                 break;
10483         }
10484         f = parms[0] + parms[1] * f;
10485         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10486                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10487         return (float) f;
10488 }
10489
10490 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10491 {
10492         int w, h, idx;
10493         float f;
10494         float tcmat[12];
10495         matrix4x4_t matrix, temp;
10496         switch(tcmod->tcmod)
10497         {
10498                 case Q3TCMOD_COUNT:
10499                 case Q3TCMOD_NONE:
10500                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10501                                 matrix = r_waterscrollmatrix;
10502                         else
10503                                 matrix = identitymatrix;
10504                         break;
10505                 case Q3TCMOD_ENTITYTRANSLATE:
10506                         // this is used in Q3 to allow the gamecode to control texcoord
10507                         // scrolling on the entity, which is not supported in darkplaces yet.
10508                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10509                         break;
10510                 case Q3TCMOD_ROTATE:
10511                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10512                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10513                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10514                         break;
10515                 case Q3TCMOD_SCALE:
10516                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10517                         break;
10518                 case Q3TCMOD_SCROLL:
10519                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10520                         break;
10521                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10522                         w = (int) tcmod->parms[0];
10523                         h = (int) tcmod->parms[1];
10524                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10525                         f = f - floor(f);
10526                         idx = (int) floor(f * w * h);
10527                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10528                         break;
10529                 case Q3TCMOD_STRETCH:
10530                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10531                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10532                         break;
10533                 case Q3TCMOD_TRANSFORM:
10534                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10535                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10536                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10537                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10538                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10539                         break;
10540                 case Q3TCMOD_TURBULENT:
10541                         // this is handled in the RSurf_PrepareVertices function
10542                         matrix = identitymatrix;
10543                         break;
10544         }
10545         temp = *texmatrix;
10546         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10547 }
10548
10549 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10550 {
10551         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10552         char name[MAX_QPATH];
10553         skinframe_t *skinframe;
10554         unsigned char pixels[296*194];
10555         strlcpy(cache->name, skinname, sizeof(cache->name));
10556         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10557         if (developer_loading.integer)
10558                 Con_Printf("loading %s\n", name);
10559         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10560         if (!skinframe || !skinframe->base)
10561         {
10562                 unsigned char *f;
10563                 fs_offset_t filesize;
10564                 skinframe = NULL;
10565                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10566                 if (f)
10567                 {
10568                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10569                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10570                         Mem_Free(f);
10571                 }
10572         }
10573         cache->skinframe = skinframe;
10574 }
10575
10576 texture_t *R_GetCurrentTexture(texture_t *t)
10577 {
10578         int i;
10579         const entity_render_t *ent = rsurface.entity;
10580         dp_model_t *model = ent->model;
10581         q3shaderinfo_layer_tcmod_t *tcmod;
10582
10583         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10584                 return t->currentframe;
10585         t->update_lastrenderframe = r_textureframe;
10586         t->update_lastrenderentity = (void *)ent;
10587
10588         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10589                 t->camera_entity = ent->entitynumber;
10590         else
10591                 t->camera_entity = 0;
10592
10593         // switch to an alternate material if this is a q1bsp animated material
10594         {
10595                 texture_t *texture = t;
10596                 int s = rsurface.ent_skinnum;
10597                 if ((unsigned int)s >= (unsigned int)model->numskins)
10598                         s = 0;
10599                 if (model->skinscenes)
10600                 {
10601                         if (model->skinscenes[s].framecount > 1)
10602                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10603                         else
10604                                 s = model->skinscenes[s].firstframe;
10605                 }
10606                 if (s > 0)
10607                         t = t + s * model->num_surfaces;
10608                 if (t->animated)
10609                 {
10610                         // use an alternate animation if the entity's frame is not 0,
10611                         // and only if the texture has an alternate animation
10612                         if (rsurface.ent_alttextures && t->anim_total[1])
10613                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10614                         else
10615                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10616                 }
10617                 texture->currentframe = t;
10618         }
10619
10620         // update currentskinframe to be a qw skin or animation frame
10621         if (rsurface.ent_qwskin >= 0)
10622         {
10623                 i = rsurface.ent_qwskin;
10624                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10625                 {
10626                         r_qwskincache_size = cl.maxclients;
10627                         if (r_qwskincache)
10628                                 Mem_Free(r_qwskincache);
10629                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10630                 }
10631                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10632                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10633                 t->currentskinframe = r_qwskincache[i].skinframe;
10634                 if (t->currentskinframe == NULL)
10635                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10636         }
10637         else if (t->numskinframes >= 2)
10638                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10639         if (t->backgroundnumskinframes >= 2)
10640                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10641
10642         t->currentmaterialflags = t->basematerialflags;
10643         t->currentalpha = rsurface.colormod[3];
10644         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10645                 t->currentalpha *= r_wateralpha.value;
10646         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10647                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10648         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10649                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10650         if (!(rsurface.ent_flags & RENDER_LIGHT))
10651                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10652         else if (FAKELIGHT_ENABLED)
10653         {
10654                         // no modellight if using fakelight for the map
10655         }
10656         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10657         {
10658                 // pick a model lighting mode
10659                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10660                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10661                 else
10662                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10663         }
10664         if (rsurface.ent_flags & RENDER_ADDITIVE)
10665                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10666         else if (t->currentalpha < 1)
10667                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10668         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10669                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10670         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10671                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10672         if (t->backgroundnumskinframes)
10673                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10674         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10675         {
10676                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10677                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10678         }
10679         else
10680                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10681         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10682                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10683
10684         // there is no tcmod
10685         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10686         {
10687                 t->currenttexmatrix = r_waterscrollmatrix;
10688                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10689         }
10690         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10691         {
10692                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10693                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10694         }
10695
10696         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10697                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10698         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10699                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10700
10701         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10702         if (t->currentskinframe->qpixels)
10703                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10704         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10705         if (!t->basetexture)
10706                 t->basetexture = r_texture_notexture;
10707         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10708         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10709         t->nmaptexture = t->currentskinframe->nmap;
10710         if (!t->nmaptexture)
10711                 t->nmaptexture = r_texture_blanknormalmap;
10712         t->glosstexture = r_texture_black;
10713         t->glowtexture = t->currentskinframe->glow;
10714         t->fogtexture = t->currentskinframe->fog;
10715         t->reflectmasktexture = t->currentskinframe->reflect;
10716         if (t->backgroundnumskinframes)
10717         {
10718                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10719                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10720                 t->backgroundglosstexture = r_texture_black;
10721                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10722                 if (!t->backgroundnmaptexture)
10723                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10724         }
10725         else
10726         {
10727                 t->backgroundbasetexture = r_texture_white;
10728                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10729                 t->backgroundglosstexture = r_texture_black;
10730                 t->backgroundglowtexture = NULL;
10731         }
10732         t->specularpower = r_shadow_glossexponent.value;
10733         // TODO: store reference values for these in the texture?
10734         t->specularscale = 0;
10735         if (r_shadow_gloss.integer > 0)
10736         {
10737                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10738                 {
10739                         if (r_shadow_glossintensity.value > 0)
10740                         {
10741                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10742                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10743                                 t->specularscale = r_shadow_glossintensity.value;
10744                         }
10745                 }
10746                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10747                 {
10748                         t->glosstexture = r_texture_white;
10749                         t->backgroundglosstexture = r_texture_white;
10750                         t->specularscale = r_shadow_gloss2intensity.value;
10751                         t->specularpower = r_shadow_gloss2exponent.value;
10752                 }
10753         }
10754         t->specularscale *= t->specularscalemod;
10755         t->specularpower *= t->specularpowermod;
10756
10757         // lightmaps mode looks bad with dlights using actual texturing, so turn
10758         // off the colormap and glossmap, but leave the normalmap on as it still
10759         // accurately represents the shading involved
10760         if (gl_lightmaps.integer)
10761         {
10762                 t->basetexture = r_texture_grey128;
10763                 t->pantstexture = r_texture_black;
10764                 t->shirttexture = r_texture_black;
10765                 t->nmaptexture = r_texture_blanknormalmap;
10766                 t->glosstexture = r_texture_black;
10767                 t->glowtexture = NULL;
10768                 t->fogtexture = NULL;
10769                 t->reflectmasktexture = NULL;
10770                 t->backgroundbasetexture = NULL;
10771                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10772                 t->backgroundglosstexture = r_texture_black;
10773                 t->backgroundglowtexture = NULL;
10774                 t->specularscale = 0;
10775                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10776         }
10777
10778         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10779         VectorClear(t->dlightcolor);
10780         t->currentnumlayers = 0;
10781         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10782         {
10783                 int blendfunc1, blendfunc2;
10784                 qboolean depthmask;
10785                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10786                 {
10787                         blendfunc1 = GL_SRC_ALPHA;
10788                         blendfunc2 = GL_ONE;
10789                 }
10790                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10791                 {
10792                         blendfunc1 = GL_SRC_ALPHA;
10793                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10794                 }
10795                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10796                 {
10797                         blendfunc1 = t->customblendfunc[0];
10798                         blendfunc2 = t->customblendfunc[1];
10799                 }
10800                 else
10801                 {
10802                         blendfunc1 = GL_ONE;
10803                         blendfunc2 = GL_ZERO;
10804                 }
10805                 // don't colormod evilblend textures
10806                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10807                         VectorSet(t->lightmapcolor, 1, 1, 1);
10808                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10809                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10810                 {
10811                         // fullbright is not affected by r_refdef.lightmapintensity
10812                         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]);
10813                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10814                                 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]);
10815                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10816                                 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]);
10817                 }
10818                 else
10819                 {
10820                         vec3_t ambientcolor;
10821                         float colorscale;
10822                         // set the color tint used for lights affecting this surface
10823                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10824                         colorscale = 2;
10825                         // q3bsp has no lightmap updates, so the lightstylevalue that
10826                         // would normally be baked into the lightmap must be
10827                         // applied to the color
10828                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10829                         if (model->type == mod_brushq3)
10830                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10831                         colorscale *= r_refdef.lightmapintensity;
10832                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10833                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10834                         // basic lit geometry
10835                         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]);
10836                         // add pants/shirt if needed
10837                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10838                                 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]);
10839                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10840                                 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]);
10841                         // now add ambient passes if needed
10842                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10843                         {
10844                                 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]);
10845                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10846                                         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]);
10847                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10848                                         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]);
10849                         }
10850                 }
10851                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10852                         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]);
10853                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10854                 {
10855                         // if this is opaque use alpha blend which will darken the earlier
10856                         // passes cheaply.
10857                         //
10858                         // if this is an alpha blended material, all the earlier passes
10859                         // were darkened by fog already, so we only need to add the fog
10860                         // color ontop through the fog mask texture
10861                         //
10862                         // if this is an additive blended material, all the earlier passes
10863                         // were darkened by fog already, and we should not add fog color
10864                         // (because the background was not darkened, there is no fog color
10865                         // that was lost behind it).
10866                         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]);
10867                 }
10868         }
10869
10870         return t->currentframe;
10871 }
10872
10873 rsurfacestate_t rsurface;
10874
10875 void R_Mesh_ResizeArrays(int newvertices)
10876 {
10877         unsigned char *base;
10878         size_t size;
10879         if (rsurface.array_size >= newvertices)
10880                 return;
10881         if (rsurface.array_base)
10882                 Mem_Free(rsurface.array_base);
10883         rsurface.array_size = (newvertices + 1023) & ~1023;
10884         size = 0;
10885         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10886         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10887         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10888         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10889         size += rsurface.array_size * sizeof(float[3]);
10890         size += rsurface.array_size * sizeof(float[3]);
10891         size += rsurface.array_size * sizeof(float[3]);
10892         size += rsurface.array_size * sizeof(float[3]);
10893         size += rsurface.array_size * sizeof(float[3]);
10894         size += rsurface.array_size * sizeof(float[3]);
10895         size += rsurface.array_size * sizeof(float[3]);
10896         size += rsurface.array_size * sizeof(float[3]);
10897         size += rsurface.array_size * sizeof(float[4]);
10898         size += rsurface.array_size * sizeof(float[2]);
10899         size += rsurface.array_size * sizeof(float[2]);
10900         size += rsurface.array_size * sizeof(float[4]);
10901         size += rsurface.array_size * sizeof(int[3]);
10902         size += rsurface.array_size * sizeof(unsigned short[3]);
10903         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10904         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10905         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10906         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10907         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10908         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10909         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10910         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10911         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10912         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10913         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10914         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10915         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10916         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10917         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10918         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10919         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10920         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10921         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10922 }
10923
10924 void RSurf_ActiveWorldEntity(void)
10925 {
10926         int newvertices;
10927         dp_model_t *model = r_refdef.scene.worldmodel;
10928         //if (rsurface.entity == r_refdef.scene.worldentity)
10929         //      return;
10930         rsurface.entity = r_refdef.scene.worldentity;
10931         rsurface.skeleton = NULL;
10932         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10933         rsurface.ent_skinnum = 0;
10934         rsurface.ent_qwskin = -1;
10935         rsurface.ent_shadertime = 0;
10936         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10937         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10938         if (rsurface.array_size < newvertices)
10939                 R_Mesh_ResizeArrays(newvertices);
10940         rsurface.matrix = identitymatrix;
10941         rsurface.inversematrix = identitymatrix;
10942         rsurface.matrixscale = 1;
10943         rsurface.inversematrixscale = 1;
10944         R_EntityMatrix(&identitymatrix);
10945         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10946         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10947         rsurface.fograngerecip = r_refdef.fograngerecip;
10948         rsurface.fogheightfade = r_refdef.fogheightfade;
10949         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10950         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10951         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10952         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10953         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10954         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10955         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10956         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10957         rsurface.colormod[3] = 1;
10958         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);
10959         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10960         rsurface.frameblend[0].lerp = 1;
10961         rsurface.ent_alttextures = false;
10962         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10963         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10964         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10965         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10966         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10967         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10968         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10969         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10970         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10971         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10972         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10973         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10974         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10975         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10976         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10977         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10978         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10979         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10980         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10981         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10982         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10983         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10984         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10985         rsurface.modelelement3i = model->surfmesh.data_element3i;
10986         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10987         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10988         rsurface.modelelement3s = model->surfmesh.data_element3s;
10989         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10990         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10991         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10992         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10993         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10994         rsurface.modelsurfaces = model->data_surfaces;
10995         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10996         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10997         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10998         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10999         rsurface.modelgeneratedvertex = false;
11000         rsurface.batchgeneratedvertex = false;
11001         rsurface.batchfirstvertex = 0;
11002         rsurface.batchnumvertices = 0;
11003         rsurface.batchfirsttriangle = 0;
11004         rsurface.batchnumtriangles = 0;
11005         rsurface.batchvertex3f  = NULL;
11006         rsurface.batchvertex3f_vertexbuffer = NULL;
11007         rsurface.batchvertex3f_bufferoffset = 0;
11008         rsurface.batchsvector3f = NULL;
11009         rsurface.batchsvector3f_vertexbuffer = NULL;
11010         rsurface.batchsvector3f_bufferoffset = 0;
11011         rsurface.batchtvector3f = NULL;
11012         rsurface.batchtvector3f_vertexbuffer = NULL;
11013         rsurface.batchtvector3f_bufferoffset = 0;
11014         rsurface.batchnormal3f  = NULL;
11015         rsurface.batchnormal3f_vertexbuffer = NULL;
11016         rsurface.batchnormal3f_bufferoffset = 0;
11017         rsurface.batchlightmapcolor4f = NULL;
11018         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11019         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11020         rsurface.batchtexcoordtexture2f = NULL;
11021         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11022         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11023         rsurface.batchtexcoordlightmap2f = NULL;
11024         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11025         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11026         rsurface.batchvertexmesh = NULL;
11027         rsurface.batchvertexmeshbuffer = NULL;
11028         rsurface.batchvertexposition = NULL;
11029         rsurface.batchvertexpositionbuffer = NULL;
11030         rsurface.batchelement3i = NULL;
11031         rsurface.batchelement3i_indexbuffer = NULL;
11032         rsurface.batchelement3i_bufferoffset = 0;
11033         rsurface.batchelement3s = NULL;
11034         rsurface.batchelement3s_indexbuffer = NULL;
11035         rsurface.batchelement3s_bufferoffset = 0;
11036         rsurface.passcolor4f = NULL;
11037         rsurface.passcolor4f_vertexbuffer = NULL;
11038         rsurface.passcolor4f_bufferoffset = 0;
11039 }
11040
11041 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11042 {
11043         int newvertices;
11044         dp_model_t *model = ent->model;
11045         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11046         //      return;
11047         rsurface.entity = (entity_render_t *)ent;
11048         rsurface.skeleton = ent->skeleton;
11049         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11050         rsurface.ent_skinnum = ent->skinnum;
11051         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;
11052         rsurface.ent_shadertime = ent->shadertime;
11053         rsurface.ent_flags = ent->flags;
11054         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
11055         if (rsurface.array_size < newvertices)
11056                 R_Mesh_ResizeArrays(newvertices);
11057         rsurface.matrix = ent->matrix;
11058         rsurface.inversematrix = ent->inversematrix;
11059         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11060         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11061         R_EntityMatrix(&rsurface.matrix);
11062         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11063         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11064         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11065         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11066         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11067         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11068         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11069         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11070         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11071         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11072         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11073         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11074         rsurface.colormod[3] = ent->alpha;
11075         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11076         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11077         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11078         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11079         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11080         if (ent->model->brush.submodel && !prepass)
11081         {
11082                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11083                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11084         }
11085         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11086         {
11087                 if (ent->animcache_vertex3f && !r_framedata_failed)
11088                 {
11089                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11090                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11091                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11092                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11093                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11094                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11095                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11096                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11097                 }
11098                 else if (wanttangents)
11099                 {
11100                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11101                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11102                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11103                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11104                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11105                         rsurface.modelvertexmesh = NULL;
11106                         rsurface.modelvertexmeshbuffer = NULL;
11107                         rsurface.modelvertexposition = NULL;
11108                         rsurface.modelvertexpositionbuffer = NULL;
11109                 }
11110                 else if (wantnormals)
11111                 {
11112                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11113                         rsurface.modelsvector3f = NULL;
11114                         rsurface.modeltvector3f = NULL;
11115                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11116                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11117                         rsurface.modelvertexmesh = NULL;
11118                         rsurface.modelvertexmeshbuffer = NULL;
11119                         rsurface.modelvertexposition = NULL;
11120                         rsurface.modelvertexpositionbuffer = NULL;
11121                 }
11122                 else
11123                 {
11124                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11125                         rsurface.modelsvector3f = NULL;
11126                         rsurface.modeltvector3f = NULL;
11127                         rsurface.modelnormal3f = NULL;
11128                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11129                         rsurface.modelvertexmesh = NULL;
11130                         rsurface.modelvertexmeshbuffer = NULL;
11131                         rsurface.modelvertexposition = NULL;
11132                         rsurface.modelvertexpositionbuffer = NULL;
11133                 }
11134                 rsurface.modelvertex3f_vertexbuffer = 0;
11135                 rsurface.modelvertex3f_bufferoffset = 0;
11136                 rsurface.modelsvector3f_vertexbuffer = 0;
11137                 rsurface.modelsvector3f_bufferoffset = 0;
11138                 rsurface.modeltvector3f_vertexbuffer = 0;
11139                 rsurface.modeltvector3f_bufferoffset = 0;
11140                 rsurface.modelnormal3f_vertexbuffer = 0;
11141                 rsurface.modelnormal3f_bufferoffset = 0;
11142                 rsurface.modelgeneratedvertex = true;
11143         }
11144         else
11145         {
11146                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11147                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11148                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11149                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11150                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11151                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11152                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11153                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11154                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11155                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11156                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11157                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11158                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11159                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11160                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11161                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11162                 rsurface.modelgeneratedvertex = false;
11163         }
11164         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11165         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11166         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11167         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11168         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11169         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11170         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11171         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11172         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11173         rsurface.modelelement3i = model->surfmesh.data_element3i;
11174         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11175         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11176         rsurface.modelelement3s = model->surfmesh.data_element3s;
11177         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11178         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11179         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11180         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11181         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11182         rsurface.modelsurfaces = model->data_surfaces;
11183         rsurface.batchgeneratedvertex = false;
11184         rsurface.batchfirstvertex = 0;
11185         rsurface.batchnumvertices = 0;
11186         rsurface.batchfirsttriangle = 0;
11187         rsurface.batchnumtriangles = 0;
11188         rsurface.batchvertex3f  = NULL;
11189         rsurface.batchvertex3f_vertexbuffer = NULL;
11190         rsurface.batchvertex3f_bufferoffset = 0;
11191         rsurface.batchsvector3f = NULL;
11192         rsurface.batchsvector3f_vertexbuffer = NULL;
11193         rsurface.batchsvector3f_bufferoffset = 0;
11194         rsurface.batchtvector3f = NULL;
11195         rsurface.batchtvector3f_vertexbuffer = NULL;
11196         rsurface.batchtvector3f_bufferoffset = 0;
11197         rsurface.batchnormal3f  = NULL;
11198         rsurface.batchnormal3f_vertexbuffer = NULL;
11199         rsurface.batchnormal3f_bufferoffset = 0;
11200         rsurface.batchlightmapcolor4f = NULL;
11201         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11202         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11203         rsurface.batchtexcoordtexture2f = NULL;
11204         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11205         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11206         rsurface.batchtexcoordlightmap2f = NULL;
11207         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11208         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11209         rsurface.batchvertexmesh = NULL;
11210         rsurface.batchvertexmeshbuffer = NULL;
11211         rsurface.batchvertexposition = NULL;
11212         rsurface.batchvertexpositionbuffer = NULL;
11213         rsurface.batchelement3i = NULL;
11214         rsurface.batchelement3i_indexbuffer = NULL;
11215         rsurface.batchelement3i_bufferoffset = 0;
11216         rsurface.batchelement3s = NULL;
11217         rsurface.batchelement3s_indexbuffer = NULL;
11218         rsurface.batchelement3s_bufferoffset = 0;
11219         rsurface.passcolor4f = NULL;
11220         rsurface.passcolor4f_vertexbuffer = NULL;
11221         rsurface.passcolor4f_bufferoffset = 0;
11222 }
11223
11224 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)
11225 {
11226         int newvertices;
11227
11228         rsurface.entity = r_refdef.scene.worldentity;
11229         rsurface.skeleton = NULL;
11230         rsurface.ent_skinnum = 0;
11231         rsurface.ent_qwskin = -1;
11232         rsurface.ent_shadertime = shadertime;
11233         rsurface.ent_flags = entflags;
11234         rsurface.modelnumvertices = numvertices;
11235         rsurface.modelnumtriangles = numtriangles;
11236         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11237         if (rsurface.array_size < newvertices)
11238                 R_Mesh_ResizeArrays(newvertices);
11239         rsurface.matrix = *matrix;
11240         rsurface.inversematrix = *inversematrix;
11241         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11242         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11243         R_EntityMatrix(&rsurface.matrix);
11244         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11245         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11246         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11247         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11248         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11249         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11250         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11251         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11252         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11253         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11254         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11255         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11256         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);
11257         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11258         rsurface.frameblend[0].lerp = 1;
11259         rsurface.ent_alttextures = false;
11260         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11261         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11262         if (wanttangents)
11263         {
11264                 rsurface.modelvertex3f = vertex3f;
11265                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11266                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11267                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11268         }
11269         else if (wantnormals)
11270         {
11271                 rsurface.modelvertex3f = vertex3f;
11272                 rsurface.modelsvector3f = NULL;
11273                 rsurface.modeltvector3f = NULL;
11274                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11275         }
11276         else
11277         {
11278                 rsurface.modelvertex3f = vertex3f;
11279                 rsurface.modelsvector3f = NULL;
11280                 rsurface.modeltvector3f = NULL;
11281                 rsurface.modelnormal3f = NULL;
11282         }
11283         rsurface.modelvertexmesh = NULL;
11284         rsurface.modelvertexmeshbuffer = NULL;
11285         rsurface.modelvertexposition = NULL;
11286         rsurface.modelvertexpositionbuffer = NULL;
11287         rsurface.modelvertex3f_vertexbuffer = 0;
11288         rsurface.modelvertex3f_bufferoffset = 0;
11289         rsurface.modelsvector3f_vertexbuffer = 0;
11290         rsurface.modelsvector3f_bufferoffset = 0;
11291         rsurface.modeltvector3f_vertexbuffer = 0;
11292         rsurface.modeltvector3f_bufferoffset = 0;
11293         rsurface.modelnormal3f_vertexbuffer = 0;
11294         rsurface.modelnormal3f_bufferoffset = 0;
11295         rsurface.modelgeneratedvertex = true;
11296         rsurface.modellightmapcolor4f  = color4f;
11297         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11298         rsurface.modellightmapcolor4f_bufferoffset = 0;
11299         rsurface.modeltexcoordtexture2f  = texcoord2f;
11300         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11301         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11302         rsurface.modeltexcoordlightmap2f  = NULL;
11303         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11304         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11305         rsurface.modelelement3i = element3i;
11306         rsurface.modelelement3i_indexbuffer = NULL;
11307         rsurface.modelelement3i_bufferoffset = 0;
11308         rsurface.modelelement3s = element3s;
11309         rsurface.modelelement3s_indexbuffer = NULL;
11310         rsurface.modelelement3s_bufferoffset = 0;
11311         rsurface.modellightmapoffsets = NULL;
11312         rsurface.modelsurfaces = NULL;
11313         rsurface.batchgeneratedvertex = false;
11314         rsurface.batchfirstvertex = 0;
11315         rsurface.batchnumvertices = 0;
11316         rsurface.batchfirsttriangle = 0;
11317         rsurface.batchnumtriangles = 0;
11318         rsurface.batchvertex3f  = NULL;
11319         rsurface.batchvertex3f_vertexbuffer = NULL;
11320         rsurface.batchvertex3f_bufferoffset = 0;
11321         rsurface.batchsvector3f = NULL;
11322         rsurface.batchsvector3f_vertexbuffer = NULL;
11323         rsurface.batchsvector3f_bufferoffset = 0;
11324         rsurface.batchtvector3f = NULL;
11325         rsurface.batchtvector3f_vertexbuffer = NULL;
11326         rsurface.batchtvector3f_bufferoffset = 0;
11327         rsurface.batchnormal3f  = NULL;
11328         rsurface.batchnormal3f_vertexbuffer = NULL;
11329         rsurface.batchnormal3f_bufferoffset = 0;
11330         rsurface.batchlightmapcolor4f = NULL;
11331         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11332         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11333         rsurface.batchtexcoordtexture2f = NULL;
11334         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11335         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11336         rsurface.batchtexcoordlightmap2f = NULL;
11337         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11338         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11339         rsurface.batchvertexmesh = NULL;
11340         rsurface.batchvertexmeshbuffer = NULL;
11341         rsurface.batchvertexposition = NULL;
11342         rsurface.batchvertexpositionbuffer = NULL;
11343         rsurface.batchelement3i = NULL;
11344         rsurface.batchelement3i_indexbuffer = NULL;
11345         rsurface.batchelement3i_bufferoffset = 0;
11346         rsurface.batchelement3s = NULL;
11347         rsurface.batchelement3s_indexbuffer = NULL;
11348         rsurface.batchelement3s_bufferoffset = 0;
11349         rsurface.passcolor4f = NULL;
11350         rsurface.passcolor4f_vertexbuffer = NULL;
11351         rsurface.passcolor4f_bufferoffset = 0;
11352
11353         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11354         {
11355                 if ((wantnormals || wanttangents) && !normal3f)
11356                 {
11357                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11358                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11359                 }
11360                 if (wanttangents && !svector3f)
11361                 {
11362                         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);
11363                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11364                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11365                 }
11366         }
11367 }
11368
11369 float RSurf_FogPoint(const float *v)
11370 {
11371         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11372         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11373         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11374         float FogHeightFade = r_refdef.fogheightfade;
11375         float fogfrac;
11376         unsigned int fogmasktableindex;
11377         if (r_refdef.fogplaneviewabove)
11378                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11379         else
11380                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11381         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11382         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11383 }
11384
11385 float RSurf_FogVertex(const float *v)
11386 {
11387         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11388         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11389         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11390         float FogHeightFade = rsurface.fogheightfade;
11391         float fogfrac;
11392         unsigned int fogmasktableindex;
11393         if (r_refdef.fogplaneviewabove)
11394                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11395         else
11396                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11397         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11398         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11399 }
11400
11401 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11402 {
11403         int i;
11404         for (i = 0;i < numelements;i++)
11405                 outelement3i[i] = inelement3i[i] + adjust;
11406 }
11407
11408 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11409 extern cvar_t gl_vbo;
11410 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11411 {
11412         int deformindex;
11413         int firsttriangle;
11414         int numtriangles;
11415         int firstvertex;
11416         int endvertex;
11417         int numvertices;
11418         int surfacefirsttriangle;
11419         int surfacenumtriangles;
11420         int surfacefirstvertex;
11421         int surfaceendvertex;
11422         int surfacenumvertices;
11423         int needsupdate;
11424         int i, j;
11425         qboolean gaps;
11426         qboolean dynamicvertex;
11427         float amplitude;
11428         float animpos;
11429         float scale;
11430         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11431         float waveparms[4];
11432         q3shaderinfo_deform_t *deform;
11433         const msurface_t *surface, *firstsurface;
11434         r_vertexposition_t *vertexposition;
11435         r_vertexmesh_t *vertexmesh;
11436         if (!texturenumsurfaces)
11437                 return;
11438         // find vertex range of this surface batch
11439         gaps = false;
11440         firstsurface = texturesurfacelist[0];
11441         firsttriangle = firstsurface->num_firsttriangle;
11442         numtriangles = 0;
11443         firstvertex = endvertex = firstsurface->num_firstvertex;
11444         for (i = 0;i < texturenumsurfaces;i++)
11445         {
11446                 surface = texturesurfacelist[i];
11447                 if (surface != firstsurface + i)
11448                         gaps = true;
11449                 surfacefirstvertex = surface->num_firstvertex;
11450                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11451                 surfacenumtriangles = surface->num_triangles;
11452                 if (firstvertex > surfacefirstvertex)
11453                         firstvertex = surfacefirstvertex;
11454                 if (endvertex < surfaceendvertex)
11455                         endvertex = surfaceendvertex;
11456                 numtriangles += surfacenumtriangles;
11457         }
11458
11459         // we now know the vertex range used, and if there are any gaps in it
11460         rsurface.batchfirstvertex = firstvertex;
11461         rsurface.batchnumvertices = endvertex - firstvertex;
11462         rsurface.batchfirsttriangle = firsttriangle;
11463         rsurface.batchnumtriangles = numtriangles;
11464
11465         // this variable holds flags for which properties have been updated that
11466         // may require regenerating vertexmesh or vertexposition arrays...
11467         needsupdate = 0;
11468
11469         // check if any dynamic vertex processing must occur
11470         dynamicvertex = false;
11471
11472         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11473                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11474         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11475         {
11476                 switch (deform->deform)
11477                 {
11478                 default:
11479                 case Q3DEFORM_PROJECTIONSHADOW:
11480                 case Q3DEFORM_TEXT0:
11481                 case Q3DEFORM_TEXT1:
11482                 case Q3DEFORM_TEXT2:
11483                 case Q3DEFORM_TEXT3:
11484                 case Q3DEFORM_TEXT4:
11485                 case Q3DEFORM_TEXT5:
11486                 case Q3DEFORM_TEXT6:
11487                 case Q3DEFORM_TEXT7:
11488                 case Q3DEFORM_NONE:
11489                         break;
11490                 case Q3DEFORM_AUTOSPRITE:
11491                         dynamicvertex = true;
11492                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11493                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11494                         break;
11495                 case Q3DEFORM_AUTOSPRITE2:
11496                         dynamicvertex = true;
11497                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11498                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11499                         break;
11500                 case Q3DEFORM_NORMAL:
11501                         dynamicvertex = true;
11502                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11503                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11504                         break;
11505                 case Q3DEFORM_WAVE:
11506                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11507                                 break; // if wavefunc is a nop, ignore this transform
11508                         dynamicvertex = true;
11509                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11510                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11511                         break;
11512                 case Q3DEFORM_BULGE:
11513                         dynamicvertex = true;
11514                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11515                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11516                         break;
11517                 case Q3DEFORM_MOVE:
11518                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11519                                 break; // if wavefunc is a nop, ignore this transform
11520                         dynamicvertex = true;
11521                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11522                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11523                         break;
11524                 }
11525         }
11526         switch(rsurface.texture->tcgen.tcgen)
11527         {
11528         default:
11529         case Q3TCGEN_TEXTURE:
11530                 break;
11531         case Q3TCGEN_LIGHTMAP:
11532                 dynamicvertex = true;
11533                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11534                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11535                 break;
11536         case Q3TCGEN_VECTOR:
11537                 dynamicvertex = true;
11538                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11539                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11540                 break;
11541         case Q3TCGEN_ENVIRONMENT:
11542                 dynamicvertex = true;
11543                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11544                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11545                 break;
11546         }
11547         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11548         {
11549                 dynamicvertex = true;
11550                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11551                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11552         }
11553
11554         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11555         {
11556                 dynamicvertex = true;
11557                 batchneed |= BATCHNEED_NOGAPS;
11558                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11559         }
11560
11561         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11562         {
11563                 dynamicvertex = true;
11564                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11565                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11566         }
11567
11568         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11569         {
11570                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11571                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11572                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11573                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11574                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11575                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11576                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11577         }
11578
11579         // when the model data has no vertex buffer (dynamic mesh), we need to
11580         // eliminate gaps
11581         if (!rsurface.modelvertexmeshbuffer)
11582                 batchneed |= BATCHNEED_NOGAPS;
11583
11584         // if needsupdate, we have to do a dynamic vertex batch for sure
11585         if (needsupdate & batchneed)
11586                 dynamicvertex = true;
11587
11588         // see if we need to build vertexmesh from arrays
11589         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11590                 dynamicvertex = true;
11591
11592         // see if we need to build vertexposition from arrays
11593         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11594                 dynamicvertex = true;
11595
11596         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11597         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11598                 dynamicvertex = true;
11599
11600         // if there is a chance of animated vertex colors, it's a dynamic batch
11601         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11602                 dynamicvertex = true;
11603
11604         rsurface.batchvertex3f = rsurface.modelvertex3f;
11605         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11606         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11607         rsurface.batchsvector3f = rsurface.modelsvector3f;
11608         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11609         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11610         rsurface.batchtvector3f = rsurface.modeltvector3f;
11611         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11612         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11613         rsurface.batchnormal3f = rsurface.modelnormal3f;
11614         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11615         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11616         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11617         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11618         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11619         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11620         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11621         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11622         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11623         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11624         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11625         rsurface.batchvertexposition = rsurface.modelvertexposition;
11626         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11627         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11628         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11629         rsurface.batchelement3i = rsurface.modelelement3i;
11630         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11631         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11632         rsurface.batchelement3s = rsurface.modelelement3s;
11633         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11634         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11635
11636         // if any dynamic vertex processing has to occur in software, we copy the
11637         // entire surface list together before processing to rebase the vertices
11638         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11639         //
11640         // if any gaps exist and we do not have a static vertex buffer, we have to
11641         // copy the surface list together to avoid wasting upload bandwidth on the
11642         // vertices in the gaps.
11643         //
11644         // if gaps exist and we have a static vertex buffer, we still have to
11645         // combine the index buffer ranges into one dynamic index buffer.
11646         //
11647         // in all cases we end up with data that can be drawn in one call.
11648
11649         if (!dynamicvertex)
11650         {
11651                 // static vertex data, just set pointers...
11652                 rsurface.batchgeneratedvertex = false;
11653                 // if there are gaps, we want to build a combined index buffer,
11654                 // otherwise use the original static buffer with an appropriate offset
11655                 if (gaps)
11656                 {
11657                         firsttriangle = 0;
11658                         numtriangles = 0;
11659                         for (i = 0;i < texturenumsurfaces;i++)
11660                         {
11661                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11662                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11663                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11664                                 numtriangles += surfacenumtriangles;
11665                         }
11666                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11667                         rsurface.batchelement3i_indexbuffer = NULL;
11668                         rsurface.batchelement3i_bufferoffset = 0;
11669                         rsurface.batchelement3s = NULL;
11670                         rsurface.batchelement3s_indexbuffer = NULL;
11671                         rsurface.batchelement3s_bufferoffset = 0;
11672                         if (endvertex <= 65536)
11673                         {
11674                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11675                                 for (i = 0;i < numtriangles*3;i++)
11676                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11677                         }
11678                         rsurface.batchfirsttriangle = firsttriangle;
11679                         rsurface.batchnumtriangles = numtriangles;
11680                 }
11681                 return;
11682         }
11683
11684         // something needs software processing, do it for real...
11685         // we only directly handle interleaved array data in this case...
11686         rsurface.batchgeneratedvertex = true;
11687
11688         // now copy the vertex data into a combined array and make an index array
11689         // (this is what Quake3 does all the time)
11690         //if (gaps || rsurface.batchfirstvertex)
11691         {
11692                 rsurface.batchvertexposition = NULL;
11693                 rsurface.batchvertexpositionbuffer = NULL;
11694                 rsurface.batchvertexmesh = NULL;
11695                 rsurface.batchvertexmeshbuffer = NULL;
11696                 rsurface.batchvertex3f = NULL;
11697                 rsurface.batchvertex3f_vertexbuffer = NULL;
11698                 rsurface.batchvertex3f_bufferoffset = 0;
11699                 rsurface.batchsvector3f = NULL;
11700                 rsurface.batchsvector3f_vertexbuffer = NULL;
11701                 rsurface.batchsvector3f_bufferoffset = 0;
11702                 rsurface.batchtvector3f = NULL;
11703                 rsurface.batchtvector3f_vertexbuffer = NULL;
11704                 rsurface.batchtvector3f_bufferoffset = 0;
11705                 rsurface.batchnormal3f = NULL;
11706                 rsurface.batchnormal3f_vertexbuffer = NULL;
11707                 rsurface.batchnormal3f_bufferoffset = 0;
11708                 rsurface.batchlightmapcolor4f = NULL;
11709                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11710                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11711                 rsurface.batchtexcoordtexture2f = NULL;
11712                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11713                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11714                 rsurface.batchtexcoordlightmap2f = NULL;
11715                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11716                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11717                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11718                 rsurface.batchelement3i_indexbuffer = NULL;
11719                 rsurface.batchelement3i_bufferoffset = 0;
11720                 rsurface.batchelement3s = NULL;
11721                 rsurface.batchelement3s_indexbuffer = NULL;
11722                 rsurface.batchelement3s_bufferoffset = 0;
11723                 // we'll only be setting up certain arrays as needed
11724                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11725                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11726                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11727                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11728                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11729                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11730                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11731                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11732                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11733                 {
11734                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11735                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11736                 }
11737                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11738                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11739                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11740                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11741                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11742                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11743                 numvertices = 0;
11744                 numtriangles = 0;
11745                 for (i = 0;i < texturenumsurfaces;i++)
11746                 {
11747                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11748                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11749                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11750                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11751                         // copy only the data requested
11752                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11753                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11754                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11755                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11756                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11757                         {
11758                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11759                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11760                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11761                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11762                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11763                                 {
11764                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11765                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11766                                 }
11767                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11768                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11769                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11770                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11771                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11772                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11773                         }
11774                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11775                         numvertices += surfacenumvertices;
11776                         numtriangles += surfacenumtriangles;
11777                 }
11778
11779                 // generate a 16bit index array as well if possible
11780                 // (in general, dynamic batches fit)
11781                 if (numvertices <= 65536)
11782                 {
11783                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11784                         for (i = 0;i < numtriangles*3;i++)
11785                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11786                 }
11787
11788                 // since we've copied everything, the batch now starts at 0
11789                 rsurface.batchfirstvertex = 0;
11790                 rsurface.batchnumvertices = numvertices;
11791                 rsurface.batchfirsttriangle = 0;
11792                 rsurface.batchnumtriangles = numtriangles;
11793         }
11794
11795         // q1bsp surfaces rendered in vertex color mode have to have colors
11796         // calculated based on lightstyles
11797         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11798         {
11799                 // generate color arrays for the surfaces in this list
11800                 int c[4];
11801                 int scale;
11802                 int size3;
11803                 const int *offsets;
11804                 const unsigned char *lm;
11805                 numvertices = 0;
11806                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11807                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11808                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11809                 for (i = 0;i < texturenumsurfaces;i++)
11810                 {
11811                         surface = texturesurfacelist[i];
11812                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11813                         surfacenumvertices = surface->num_vertices;
11814                         if (surface->lightmapinfo->samples)
11815                         {
11816                                 for (j = 0;j < surfacenumvertices;j++)
11817                                 {
11818                                         lm = surface->lightmapinfo->samples + offsets[j];
11819                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11820                                         VectorScale(lm, scale, c);
11821                                         if (surface->lightmapinfo->styles[1] != 255)
11822                                         {
11823                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11824                                                 lm += size3;
11825                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11826                                                 VectorMA(c, scale, lm, c);
11827                                                 if (surface->lightmapinfo->styles[2] != 255)
11828                                                 {
11829                                                         lm += size3;
11830                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11831                                                         VectorMA(c, scale, lm, c);
11832                                                         if (surface->lightmapinfo->styles[3] != 255)
11833                                                         {
11834                                                                 lm += size3;
11835                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11836                                                                 VectorMA(c, scale, lm, c);
11837                                                         }
11838                                                 }
11839                                         }
11840                                         c[0] >>= 15;
11841                                         c[1] >>= 15;
11842                                         c[2] >>= 15;
11843                                         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);
11844                                         numvertices++;
11845                                 }
11846                         }
11847                         else
11848                         {
11849                                 for (j = 0;j < surfacenumvertices;j++)
11850                                 {
11851                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11852                                         numvertices++;
11853                                 }
11854                         }
11855                 }
11856         }
11857
11858         // if vertices are deformed (sprite flares and things in maps, possibly
11859         // water waves, bulges and other deformations), modify the copied vertices
11860         // in place
11861         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11862         {
11863                 switch (deform->deform)
11864                 {
11865                 default:
11866                 case Q3DEFORM_PROJECTIONSHADOW:
11867                 case Q3DEFORM_TEXT0:
11868                 case Q3DEFORM_TEXT1:
11869                 case Q3DEFORM_TEXT2:
11870                 case Q3DEFORM_TEXT3:
11871                 case Q3DEFORM_TEXT4:
11872                 case Q3DEFORM_TEXT5:
11873                 case Q3DEFORM_TEXT6:
11874                 case Q3DEFORM_TEXT7:
11875                 case Q3DEFORM_NONE:
11876                         break;
11877                 case Q3DEFORM_AUTOSPRITE:
11878                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11879                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11880                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11881                         VectorNormalize(newforward);
11882                         VectorNormalize(newright);
11883                         VectorNormalize(newup);
11884                         // a single autosprite surface can contain multiple sprites...
11885                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11886                         {
11887                                 VectorClear(center);
11888                                 for (i = 0;i < 4;i++)
11889                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11890                                 VectorScale(center, 0.25f, center);
11891                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11892                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11893                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11894                                 for (i = 0;i < 4;i++)
11895                                 {
11896                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11897                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11898                                 }
11899                         }
11900                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11901                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11902                         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);
11903                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11904                         rsurface.batchvertex3f_vertexbuffer = NULL;
11905                         rsurface.batchvertex3f_bufferoffset = 0;
11906                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11907                         rsurface.batchsvector3f_vertexbuffer = NULL;
11908                         rsurface.batchsvector3f_bufferoffset = 0;
11909                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11910                         rsurface.batchtvector3f_vertexbuffer = NULL;
11911                         rsurface.batchtvector3f_bufferoffset = 0;
11912                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11913                         rsurface.batchnormal3f_vertexbuffer = NULL;
11914                         rsurface.batchnormal3f_bufferoffset = 0;
11915                         break;
11916                 case Q3DEFORM_AUTOSPRITE2:
11917                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11918                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11919                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11920                         VectorNormalize(newforward);
11921                         VectorNormalize(newright);
11922                         VectorNormalize(newup);
11923                         {
11924                                 const float *v1, *v2;
11925                                 vec3_t start, end;
11926                                 float f, l;
11927                                 struct
11928                                 {
11929                                         float length2;
11930                                         const float *v1;
11931                                         const float *v2;
11932                                 }
11933                                 shortest[2];
11934                                 memset(shortest, 0, sizeof(shortest));
11935                                 // a single autosprite surface can contain multiple sprites...
11936                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11937                                 {
11938                                         VectorClear(center);
11939                                         for (i = 0;i < 4;i++)
11940                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11941                                         VectorScale(center, 0.25f, center);
11942                                         // find the two shortest edges, then use them to define the
11943                                         // axis vectors for rotating around the central axis
11944                                         for (i = 0;i < 6;i++)
11945                                         {
11946                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11947                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11948                                                 l = VectorDistance2(v1, v2);
11949                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11950                                                 if (v1[2] != v2[2])
11951                                                         l += (1.0f / 1024.0f);
11952                                                 if (shortest[0].length2 > l || i == 0)
11953                                                 {
11954                                                         shortest[1] = shortest[0];
11955                                                         shortest[0].length2 = l;
11956                                                         shortest[0].v1 = v1;
11957                                                         shortest[0].v2 = v2;
11958                                                 }
11959                                                 else if (shortest[1].length2 > l || i == 1)
11960                                                 {
11961                                                         shortest[1].length2 = l;
11962                                                         shortest[1].v1 = v1;
11963                                                         shortest[1].v2 = v2;
11964                                                 }
11965                                         }
11966                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11967                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11968                                         // this calculates the right vector from the shortest edge
11969                                         // and the up vector from the edge midpoints
11970                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11971                                         VectorNormalize(right);
11972                                         VectorSubtract(end, start, up);
11973                                         VectorNormalize(up);
11974                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11975                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11976                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11977                                         VectorNegate(forward, forward);
11978                                         VectorReflect(forward, 0, up, forward);
11979                                         VectorNormalize(forward);
11980                                         CrossProduct(up, forward, newright);
11981                                         VectorNormalize(newright);
11982                                         // rotate the quad around the up axis vector, this is made
11983                                         // especially easy by the fact we know the quad is flat,
11984                                         // so we only have to subtract the center position and
11985                                         // measure distance along the right vector, and then
11986                                         // multiply that by the newright vector and add back the
11987                                         // center position
11988                                         // we also need to subtract the old position to undo the
11989                                         // displacement from the center, which we do with a
11990                                         // DotProduct, the subtraction/addition of center is also
11991                                         // optimized into DotProducts here
11992                                         l = DotProduct(right, center);
11993                                         for (i = 0;i < 4;i++)
11994                                         {
11995                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11996                                                 f = DotProduct(right, v1) - l;
11997                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11998                                         }
11999                                 }
12000                         }
12001                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12002                         rsurface.batchvertex3f_vertexbuffer = NULL;
12003                         rsurface.batchvertex3f_bufferoffset = 0;
12004                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12005                         {
12006                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12007                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12008                                 rsurface.batchnormal3f_vertexbuffer = NULL;
12009                                 rsurface.batchnormal3f_bufferoffset = 0;
12010                         }
12011                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12012                         {
12013                                 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);
12014                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12015                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12016                                 rsurface.batchsvector3f_bufferoffset = 0;
12017                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12018                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12019                                 rsurface.batchtvector3f_bufferoffset = 0;
12020                         }
12021                         break;
12022                 case Q3DEFORM_NORMAL:
12023                         // deform the normals to make reflections wavey
12024                         for (j = 0;j < rsurface.batchnumvertices;j++)
12025                         {
12026                                 float vertex[3];
12027                                 float *normal = rsurface.array_batchnormal3f + 3*j;
12028                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12029                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12030                                 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]);
12031                                 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]);
12032                                 VectorNormalize(normal);
12033                         }
12034                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12035                         rsurface.batchnormal3f_vertexbuffer = NULL;
12036                         rsurface.batchnormal3f_bufferoffset = 0;
12037                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12038                         {
12039                                 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);
12040                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12041                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12042                                 rsurface.batchsvector3f_bufferoffset = 0;
12043                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12044                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12045                                 rsurface.batchtvector3f_bufferoffset = 0;
12046                         }
12047                         break;
12048                 case Q3DEFORM_WAVE:
12049                         // deform vertex array to make wavey water and flags and such
12050                         waveparms[0] = deform->waveparms[0];
12051                         waveparms[1] = deform->waveparms[1];
12052                         waveparms[2] = deform->waveparms[2];
12053                         waveparms[3] = deform->waveparms[3];
12054                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12055                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12056                         // this is how a divisor of vertex influence on deformation
12057                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12058                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12059                         for (j = 0;j < rsurface.batchnumvertices;j++)
12060                         {
12061                                 // if the wavefunc depends on time, evaluate it per-vertex
12062                                 if (waveparms[3])
12063                                 {
12064                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12065                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12066                                 }
12067                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12068                         }
12069                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12070                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12071                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12072                         rsurface.batchvertex3f_vertexbuffer = NULL;
12073                         rsurface.batchvertex3f_bufferoffset = 0;
12074                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12075                         rsurface.batchnormal3f_vertexbuffer = NULL;
12076                         rsurface.batchnormal3f_bufferoffset = 0;
12077                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12078                         {
12079                                 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);
12080                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12081                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12082                                 rsurface.batchsvector3f_bufferoffset = 0;
12083                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12084                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12085                                 rsurface.batchtvector3f_bufferoffset = 0;
12086                         }
12087                         break;
12088                 case Q3DEFORM_BULGE:
12089                         // deform vertex array to make the surface have moving bulges
12090                         for (j = 0;j < rsurface.batchnumvertices;j++)
12091                         {
12092                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12093                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12094                         }
12095                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12096                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12097                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12098                         rsurface.batchvertex3f_vertexbuffer = NULL;
12099                         rsurface.batchvertex3f_bufferoffset = 0;
12100                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12101                         rsurface.batchnormal3f_vertexbuffer = NULL;
12102                         rsurface.batchnormal3f_bufferoffset = 0;
12103                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12104                         {
12105                                 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);
12106                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12107                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12108                                 rsurface.batchsvector3f_bufferoffset = 0;
12109                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12110                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12111                                 rsurface.batchtvector3f_bufferoffset = 0;
12112                         }
12113                         break;
12114                 case Q3DEFORM_MOVE:
12115                         // deform vertex array
12116                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12117                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12118                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12119                         VectorScale(deform->parms, scale, waveparms);
12120                         for (j = 0;j < rsurface.batchnumvertices;j++)
12121                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12122                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12123                         rsurface.batchvertex3f_vertexbuffer = NULL;
12124                         rsurface.batchvertex3f_bufferoffset = 0;
12125                         break;
12126                 }
12127         }
12128
12129         // generate texcoords based on the chosen texcoord source
12130         switch(rsurface.texture->tcgen.tcgen)
12131         {
12132         default:
12133         case Q3TCGEN_TEXTURE:
12134                 break;
12135         case Q3TCGEN_LIGHTMAP:
12136                 if (rsurface.batchtexcoordlightmap2f)
12137                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12138                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12139                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12140                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12141                 break;
12142         case Q3TCGEN_VECTOR:
12143                 for (j = 0;j < rsurface.batchnumvertices;j++)
12144                 {
12145                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12146                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12147                 }
12148                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12149                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12150                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12151                 break;
12152         case Q3TCGEN_ENVIRONMENT:
12153                 // make environment reflections using a spheremap
12154                 for (j = 0;j < rsurface.batchnumvertices;j++)
12155                 {
12156                         // identical to Q3A's method, but executed in worldspace so
12157                         // carried models can be shiny too
12158
12159                         float viewer[3], d, reflected[3], worldreflected[3];
12160
12161                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12162                         // VectorNormalize(viewer);
12163
12164                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12165
12166                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12167                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12168                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12169                         // note: this is proportinal to viewer, so we can normalize later
12170
12171                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12172                         VectorNormalize(worldreflected);
12173
12174                         // note: this sphere map only uses world x and z!
12175                         // so positive and negative y will LOOK THE SAME.
12176                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12177                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12178                 }
12179                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12180                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12181                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12182                 break;
12183         }
12184         // the only tcmod that needs software vertex processing is turbulent, so
12185         // check for it here and apply the changes if needed
12186         // and we only support that as the first one
12187         // (handling a mixture of turbulent and other tcmods would be problematic
12188         //  without punting it entirely to a software path)
12189         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12190         {
12191                 amplitude = rsurface.texture->tcmods[0].parms[1];
12192                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12193                 for (j = 0;j < rsurface.batchnumvertices;j++)
12194                 {
12195                         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);
12196                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12197                 }
12198                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12199                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12200                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12201         }
12202
12203         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12204         {
12205                 // convert the modified arrays to vertex structs
12206                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12207                 rsurface.batchvertexmeshbuffer = NULL;
12208                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12209                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12210                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12211                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12212                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12213                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12214                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12215                 {
12216                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12217                         {
12218                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12219                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12220                         }
12221                 }
12222                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12223                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12224                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12225                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12226                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12227                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12228                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12229                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12230                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12231         }
12232
12233         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12234         {
12235                 // convert the modified arrays to vertex structs
12236                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12237                 rsurface.batchvertexpositionbuffer = NULL;
12238                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12239                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12240                 else
12241                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12242                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12243         }
12244 }
12245
12246 void RSurf_DrawBatch(void)
12247 {
12248         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12249         // through the pipeline, killing it earlier in the pipeline would have
12250         // per-surface overhead rather than per-batch overhead, so it's best to
12251         // reject it here, before it hits glDraw.
12252         if (rsurface.batchnumtriangles == 0)
12253                 return;
12254 #if 0
12255         // batch debugging code
12256         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12257         {
12258                 int i;
12259                 int j;
12260                 int c;
12261                 const int *e;
12262                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12263                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12264                 {
12265                         c = e[i];
12266                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12267                         {
12268                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12269                                 {
12270                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12271                                                 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);
12272                                         break;
12273                                 }
12274                         }
12275                 }
12276         }
12277 #endif
12278         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);
12279 }
12280
12281 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12282 {
12283         // pick the closest matching water plane
12284         int planeindex, vertexindex, bestplaneindex = -1;
12285         float d, bestd;
12286         vec3_t vert;
12287         const float *v;
12288         r_waterstate_waterplane_t *p;
12289         qboolean prepared = false;
12290         bestd = 0;
12291         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12292         {
12293                 if(p->camera_entity != rsurface.texture->camera_entity)
12294                         continue;
12295                 d = 0;
12296                 if(!prepared)
12297                 {
12298                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12299                         prepared = true;
12300                         if(rsurface.batchnumvertices == 0)
12301                                 break;
12302                 }
12303                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12304                 {
12305                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12306                         d += fabs(PlaneDiff(vert, &p->plane));
12307                 }
12308                 if (bestd > d || bestplaneindex < 0)
12309                 {
12310                         bestd = d;
12311                         bestplaneindex = planeindex;
12312                 }
12313         }
12314         return bestplaneindex;
12315         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12316         // this situation though, as it might be better to render single larger
12317         // batches with useless stuff (backface culled for example) than to
12318         // render multiple smaller batches
12319 }
12320
12321 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12322 {
12323         int i;
12324         for (i = 0;i < rsurface.batchnumvertices;i++)
12325                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12326         rsurface.passcolor4f = rsurface.array_passcolor4f;
12327         rsurface.passcolor4f_vertexbuffer = 0;
12328         rsurface.passcolor4f_bufferoffset = 0;
12329 }
12330
12331 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12332 {
12333         int i;
12334         float f;
12335         const float *v;
12336         const float *c;
12337         float *c2;
12338         if (rsurface.passcolor4f)
12339         {
12340                 // generate color arrays
12341                 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)
12342                 {
12343                         f = RSurf_FogVertex(v);
12344                         c2[0] = c[0] * f;
12345                         c2[1] = c[1] * f;
12346                         c2[2] = c[2] * f;
12347                         c2[3] = c[3];
12348                 }
12349         }
12350         else
12351         {
12352                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12353                 {
12354                         f = RSurf_FogVertex(v);
12355                         c2[0] = f;
12356                         c2[1] = f;
12357                         c2[2] = f;
12358                         c2[3] = 1;
12359                 }
12360         }
12361         rsurface.passcolor4f = rsurface.array_passcolor4f;
12362         rsurface.passcolor4f_vertexbuffer = 0;
12363         rsurface.passcolor4f_bufferoffset = 0;
12364 }
12365
12366 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12367 {
12368         int i;
12369         float f;
12370         const float *v;
12371         const float *c;
12372         float *c2;
12373         if (!rsurface.passcolor4f)
12374                 return;
12375         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)
12376         {
12377                 f = RSurf_FogVertex(v);
12378                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12379                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12380                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12381                 c2[3] = c[3];
12382         }
12383         rsurface.passcolor4f = rsurface.array_passcolor4f;
12384         rsurface.passcolor4f_vertexbuffer = 0;
12385         rsurface.passcolor4f_bufferoffset = 0;
12386 }
12387
12388 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12389 {
12390         int i;
12391         const float *c;
12392         float *c2;
12393         if (!rsurface.passcolor4f)
12394                 return;
12395         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12396         {
12397                 c2[0] = c[0] * r;
12398                 c2[1] = c[1] * g;
12399                 c2[2] = c[2] * b;
12400                 c2[3] = c[3] * a;
12401         }
12402         rsurface.passcolor4f = rsurface.array_passcolor4f;
12403         rsurface.passcolor4f_vertexbuffer = 0;
12404         rsurface.passcolor4f_bufferoffset = 0;
12405 }
12406
12407 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12408 {
12409         int i;
12410         const float *c;
12411         float *c2;
12412         if (!rsurface.passcolor4f)
12413                 return;
12414         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12415         {
12416                 c2[0] = c[0] + r_refdef.scene.ambient;
12417                 c2[1] = c[1] + r_refdef.scene.ambient;
12418                 c2[2] = c[2] + r_refdef.scene.ambient;
12419                 c2[3] = c[3];
12420         }
12421         rsurface.passcolor4f = rsurface.array_passcolor4f;
12422         rsurface.passcolor4f_vertexbuffer = 0;
12423         rsurface.passcolor4f_bufferoffset = 0;
12424 }
12425
12426 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12427 {
12428         // TODO: optimize
12429         rsurface.passcolor4f = NULL;
12430         rsurface.passcolor4f_vertexbuffer = 0;
12431         rsurface.passcolor4f_bufferoffset = 0;
12432         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12433         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12434         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12435         GL_Color(r, g, b, a);
12436         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12437         RSurf_DrawBatch();
12438 }
12439
12440 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12441 {
12442         // TODO: optimize applyfog && applycolor case
12443         // just apply fog if necessary, and tint the fog color array if necessary
12444         rsurface.passcolor4f = NULL;
12445         rsurface.passcolor4f_vertexbuffer = 0;
12446         rsurface.passcolor4f_bufferoffset = 0;
12447         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12448         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12449         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12450         GL_Color(r, g, b, a);
12451         RSurf_DrawBatch();
12452 }
12453
12454 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12455 {
12456         // TODO: optimize
12457         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12458         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12459         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12460         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12461         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12462         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12463         GL_Color(r, g, b, a);
12464         RSurf_DrawBatch();
12465 }
12466
12467 static void RSurf_DrawBatch_GL11_ClampColor(void)
12468 {
12469         int i;
12470         const float *c1;
12471         float *c2;
12472         if (!rsurface.passcolor4f)
12473                 return;
12474         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12475         {
12476                 c2[0] = bound(0.0f, c1[0], 1.0f);
12477                 c2[1] = bound(0.0f, c1[1], 1.0f);
12478                 c2[2] = bound(0.0f, c1[2], 1.0f);
12479                 c2[3] = bound(0.0f, c1[3], 1.0f);
12480         }
12481 }
12482
12483 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12484 {
12485         int i;
12486         float f;
12487         const float *v;
12488         const float *n;
12489         float *c;
12490         //vec3_t eyedir;
12491
12492         // fake shading
12493         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)
12494         {
12495                 f = -DotProduct(r_refdef.view.forward, n);
12496                 f = max(0, f);
12497                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12498                 f *= r_refdef.lightmapintensity;
12499                 Vector4Set(c, f, f, f, 1);
12500         }
12501
12502         rsurface.passcolor4f = rsurface.array_passcolor4f;
12503         rsurface.passcolor4f_vertexbuffer = 0;
12504         rsurface.passcolor4f_bufferoffset = 0;
12505 }
12506
12507 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12508 {
12509         RSurf_DrawBatch_GL11_ApplyFakeLight();
12510         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12511         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12512         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12513         GL_Color(r, g, b, a);
12514         RSurf_DrawBatch();
12515 }
12516
12517 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12518 {
12519         int i;
12520         float f;
12521         float alpha;
12522         const float *v;
12523         const float *n;
12524         float *c;
12525         vec3_t ambientcolor;
12526         vec3_t diffusecolor;
12527         vec3_t lightdir;
12528         // TODO: optimize
12529         // model lighting
12530         VectorCopy(rsurface.modellight_lightdir, lightdir);
12531         f = 0.5f * r_refdef.lightmapintensity;
12532         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12533         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12534         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12535         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12536         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12537         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12538         alpha = *a;
12539         if (VectorLength2(diffusecolor) > 0)
12540         {
12541                 // q3-style directional shading
12542                 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)
12543                 {
12544                         if ((f = DotProduct(n, lightdir)) > 0)
12545                                 VectorMA(ambientcolor, f, diffusecolor, c);
12546                         else
12547                                 VectorCopy(ambientcolor, c);
12548                         c[3] = alpha;
12549                 }
12550                 *r = 1;
12551                 *g = 1;
12552                 *b = 1;
12553                 *a = 1;
12554                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12555                 rsurface.passcolor4f_vertexbuffer = 0;
12556                 rsurface.passcolor4f_bufferoffset = 0;
12557                 *applycolor = false;
12558         }
12559         else
12560         {
12561                 *r = ambientcolor[0];
12562                 *g = ambientcolor[1];
12563                 *b = ambientcolor[2];
12564                 rsurface.passcolor4f = NULL;
12565                 rsurface.passcolor4f_vertexbuffer = 0;
12566                 rsurface.passcolor4f_bufferoffset = 0;
12567         }
12568 }
12569
12570 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12571 {
12572         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12573         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12574         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12575         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12576         GL_Color(r, g, b, a);
12577         RSurf_DrawBatch();
12578 }
12579
12580 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12581 {
12582         int i;
12583         float f;
12584         const float *v;
12585         float *c;
12586         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12587         {
12588                 f = 1 - RSurf_FogVertex(v);
12589                 c[0] = r;
12590                 c[1] = g;
12591                 c[2] = b;
12592                 c[3] = f * a;
12593         }
12594 }
12595
12596 void RSurf_SetupDepthAndCulling(void)
12597 {
12598         // submodels are biased to avoid z-fighting with world surfaces that they
12599         // may be exactly overlapping (avoids z-fighting artifacts on certain
12600         // doors and things in Quake maps)
12601         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12602         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12603         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12604         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12605 }
12606
12607 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12608 {
12609         // transparent sky would be ridiculous
12610         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12611                 return;
12612         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12613         skyrenderlater = true;
12614         RSurf_SetupDepthAndCulling();
12615         GL_DepthMask(true);
12616         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12617         // skymasking on them, and Quake3 never did sky masking (unlike
12618         // software Quake and software Quake2), so disable the sky masking
12619         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12620         // and skymasking also looks very bad when noclipping outside the
12621         // level, so don't use it then either.
12622         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12623         {
12624                 R_Mesh_ResetTextureState();
12625                 if (skyrendermasked)
12626                 {
12627                         R_SetupShader_DepthOrShadow();
12628                         // depth-only (masking)
12629                         GL_ColorMask(0,0,0,0);
12630                         // just to make sure that braindead drivers don't draw
12631                         // anything despite that colormask...
12632                         GL_BlendFunc(GL_ZERO, GL_ONE);
12633                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12634                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12635                 }
12636                 else
12637                 {
12638                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12639                         // fog sky
12640                         GL_BlendFunc(GL_ONE, GL_ZERO);
12641                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12642                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12643                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12644                 }
12645                 RSurf_DrawBatch();
12646                 if (skyrendermasked)
12647                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12648         }
12649         R_Mesh_ResetTextureState();
12650         GL_Color(1, 1, 1, 1);
12651 }
12652
12653 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12654 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12655 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12656 {
12657         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12658                 return;
12659         if (prepass)
12660         {
12661                 // render screenspace normalmap to texture
12662                 GL_DepthMask(true);
12663                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12664                 RSurf_DrawBatch();
12665                 return;
12666         }
12667
12668         // bind lightmap texture
12669
12670         // water/refraction/reflection/camera surfaces have to be handled specially
12671         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12672         {
12673                 int start, end, startplaneindex;
12674                 for (start = 0;start < texturenumsurfaces;start = end)
12675                 {
12676                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12677                         if(startplaneindex < 0)
12678                         {
12679                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12680                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12681                                 end = start + 1;
12682                                 continue;
12683                         }
12684                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12685                                 ;
12686                         // now that we have a batch using the same planeindex, render it
12687                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12688                         {
12689                                 // render water or distortion background
12690                                 GL_DepthMask(true);
12691                                 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));
12692                                 RSurf_DrawBatch();
12693                                 // blend surface on top
12694                                 GL_DepthMask(false);
12695                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12696                                 RSurf_DrawBatch();
12697                         }
12698                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12699                         {
12700                                 // render surface with reflection texture as input
12701                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12702                                 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));
12703                                 RSurf_DrawBatch();
12704                         }
12705                 }
12706                 return;
12707         }
12708
12709         // render surface batch normally
12710         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12711         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12712         RSurf_DrawBatch();
12713 }
12714
12715 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12716 {
12717         // OpenGL 1.3 path - anything not completely ancient
12718         qboolean applycolor;
12719         qboolean applyfog;
12720         int layerindex;
12721         const texturelayer_t *layer;
12722         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);
12723         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12724
12725         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12726         {
12727                 vec4_t layercolor;
12728                 int layertexrgbscale;
12729                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12730                 {
12731                         if (layerindex == 0)
12732                                 GL_AlphaTest(true);
12733                         else
12734                         {
12735                                 GL_AlphaTest(false);
12736                                 GL_DepthFunc(GL_EQUAL);
12737                         }
12738                 }
12739                 GL_DepthMask(layer->depthmask && writedepth);
12740                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12741                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12742                 {
12743                         layertexrgbscale = 4;
12744                         VectorScale(layer->color, 0.25f, layercolor);
12745                 }
12746                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12747                 {
12748                         layertexrgbscale = 2;
12749                         VectorScale(layer->color, 0.5f, layercolor);
12750                 }
12751                 else
12752                 {
12753                         layertexrgbscale = 1;
12754                         VectorScale(layer->color, 1.0f, layercolor);
12755                 }
12756                 layercolor[3] = layer->color[3];
12757                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12758                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12759                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12760                 switch (layer->type)
12761                 {
12762                 case TEXTURELAYERTYPE_LITTEXTURE:
12763                         // single-pass lightmapped texture with 2x rgbscale
12764                         R_Mesh_TexBind(0, r_texture_white);
12765                         R_Mesh_TexMatrix(0, NULL);
12766                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12767                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12768                         R_Mesh_TexBind(1, layer->texture);
12769                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12770                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12771                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12772                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12773                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12774                         else if (FAKELIGHT_ENABLED)
12775                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12776                         else if (rsurface.uselightmaptexture)
12777                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12778                         else
12779                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12780                         break;
12781                 case TEXTURELAYERTYPE_TEXTURE:
12782                         // singletexture unlit texture with transparency support
12783                         R_Mesh_TexBind(0, layer->texture);
12784                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12785                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12786                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12787                         R_Mesh_TexBind(1, 0);
12788                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12789                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12790                         break;
12791                 case TEXTURELAYERTYPE_FOG:
12792                         // singletexture fogging
12793                         if (layer->texture)
12794                         {
12795                                 R_Mesh_TexBind(0, layer->texture);
12796                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12797                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12798                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12799                         }
12800                         else
12801                         {
12802                                 R_Mesh_TexBind(0, 0);
12803                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12804                         }
12805                         R_Mesh_TexBind(1, 0);
12806                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12807                         // generate a color array for the fog pass
12808                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12809                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12810                         RSurf_DrawBatch();
12811                         break;
12812                 default:
12813                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12814                 }
12815         }
12816         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12817         {
12818                 GL_DepthFunc(GL_LEQUAL);
12819                 GL_AlphaTest(false);
12820         }
12821 }
12822
12823 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12824 {
12825         // OpenGL 1.1 - crusty old voodoo path
12826         qboolean applyfog;
12827         int layerindex;
12828         const texturelayer_t *layer;
12829         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);
12830         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12831
12832         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12833         {
12834                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12835                 {
12836                         if (layerindex == 0)
12837                                 GL_AlphaTest(true);
12838                         else
12839                         {
12840                                 GL_AlphaTest(false);
12841                                 GL_DepthFunc(GL_EQUAL);
12842                         }
12843                 }
12844                 GL_DepthMask(layer->depthmask && writedepth);
12845                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12846                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12847                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12848                 switch (layer->type)
12849                 {
12850                 case TEXTURELAYERTYPE_LITTEXTURE:
12851                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12852                         {
12853                                 // two-pass lit texture with 2x rgbscale
12854                                 // first the lightmap pass
12855                                 R_Mesh_TexBind(0, r_texture_white);
12856                                 R_Mesh_TexMatrix(0, NULL);
12857                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12858                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12859                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12860                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12861                                 else if (FAKELIGHT_ENABLED)
12862                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12863                                 else if (rsurface.uselightmaptexture)
12864                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12865                                 else
12866                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12867                                 // then apply the texture to it
12868                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12869                                 R_Mesh_TexBind(0, layer->texture);
12870                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12871                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12872                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12873                                 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);
12874                         }
12875                         else
12876                         {
12877                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12878                                 R_Mesh_TexBind(0, layer->texture);
12879                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12880                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12881                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12882                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12883                                         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);
12884                                 else
12885                                         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);
12886                         }
12887                         break;
12888                 case TEXTURELAYERTYPE_TEXTURE:
12889                         // singletexture unlit texture with transparency support
12890                         R_Mesh_TexBind(0, layer->texture);
12891                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12892                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12893                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12894                         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);
12895                         break;
12896                 case TEXTURELAYERTYPE_FOG:
12897                         // singletexture fogging
12898                         if (layer->texture)
12899                         {
12900                                 R_Mesh_TexBind(0, layer->texture);
12901                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12902                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12903                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12904                         }
12905                         else
12906                         {
12907                                 R_Mesh_TexBind(0, 0);
12908                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12909                         }
12910                         // generate a color array for the fog pass
12911                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12912                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12913                         RSurf_DrawBatch();
12914                         break;
12915                 default:
12916                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12917                 }
12918         }
12919         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12920         {
12921                 GL_DepthFunc(GL_LEQUAL);
12922                 GL_AlphaTest(false);
12923         }
12924 }
12925
12926 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12927 {
12928         int vi;
12929         int j;
12930         r_vertexgeneric_t *batchvertex;
12931         float c[4];
12932
12933         GL_AlphaTest(false);
12934 //      R_Mesh_ResetTextureState();
12935         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12936
12937         if(rsurface.texture && rsurface.texture->currentskinframe)
12938         {
12939                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12940                 c[3] *= rsurface.texture->currentalpha;
12941         }
12942         else
12943         {
12944                 c[0] = 1;
12945                 c[1] = 0;
12946                 c[2] = 1;
12947                 c[3] = 1;
12948         }
12949
12950         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12951         {
12952                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12953                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12954                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12955         }
12956
12957         // brighten it up (as texture value 127 means "unlit")
12958         c[0] *= 2 * r_refdef.view.colorscale;
12959         c[1] *= 2 * r_refdef.view.colorscale;
12960         c[2] *= 2 * r_refdef.view.colorscale;
12961
12962         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12963                 c[3] *= r_wateralpha.value;
12964
12965         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12966         {
12967                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12968                 GL_DepthMask(false);
12969         }
12970         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12971         {
12972                 GL_BlendFunc(GL_ONE, GL_ONE);
12973                 GL_DepthMask(false);
12974         }
12975         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12976         {
12977                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12978                 GL_DepthMask(false);
12979         }
12980         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12981         {
12982                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12983                 GL_DepthMask(false);
12984         }
12985         else
12986         {
12987                 GL_BlendFunc(GL_ONE, GL_ZERO);
12988                 GL_DepthMask(writedepth);
12989         }
12990
12991         if (r_showsurfaces.integer == 3)
12992         {
12993                 rsurface.passcolor4f = NULL;
12994
12995                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12996                 {
12997                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12998
12999                         rsurface.passcolor4f = NULL;
13000                         rsurface.passcolor4f_vertexbuffer = 0;
13001                         rsurface.passcolor4f_bufferoffset = 0;
13002                 }
13003                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13004                 {
13005                         qboolean applycolor = true;
13006                         float one = 1.0;
13007
13008                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13009
13010                         r_refdef.lightmapintensity = 1;
13011                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13012                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13013                 }
13014                 else if (FAKELIGHT_ENABLED)
13015                 {
13016                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13017
13018                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13019                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13020                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13021                 }
13022                 else
13023                 {
13024                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13025
13026                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13027                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13028                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13029                 }
13030
13031                 if(!rsurface.passcolor4f)
13032                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13033
13034                 RSurf_DrawBatch_GL11_ApplyAmbient();
13035                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13036                 if(r_refdef.fogenabled)
13037                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13038                 RSurf_DrawBatch_GL11_ClampColor();
13039
13040                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13041                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13042                 RSurf_DrawBatch();
13043         }
13044         else if (!r_refdef.view.showdebug)
13045         {
13046                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13047                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13048                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13049                 {
13050                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13051                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13052                 }
13053                 R_Mesh_PrepareVertices_Generic_Unlock();
13054                 RSurf_DrawBatch();
13055         }
13056         else if (r_showsurfaces.integer == 4)
13057         {
13058                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13059                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13060                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13061                 {
13062                         unsigned char c = vi << 3;
13063                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13064                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13065                 }
13066                 R_Mesh_PrepareVertices_Generic_Unlock();
13067                 RSurf_DrawBatch();
13068         }
13069         else if (r_showsurfaces.integer == 2)
13070         {
13071                 const int *e;
13072                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13073                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13074                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13075                 {
13076                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13077                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13078                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13079                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13080                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13081                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13082                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13083                 }
13084                 R_Mesh_PrepareVertices_Generic_Unlock();
13085                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13086         }
13087         else
13088         {
13089                 int texturesurfaceindex;
13090                 int k;
13091                 const msurface_t *surface;
13092                 unsigned char surfacecolor4ub[4];
13093                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13094                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13095                 vi = 0;
13096                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13097                 {
13098                         surface = texturesurfacelist[texturesurfaceindex];
13099                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13100                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13101                         for (j = 0;j < surface->num_vertices;j++)
13102                         {
13103                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13104                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13105                                 vi++;
13106                         }
13107                 }
13108                 R_Mesh_PrepareVertices_Generic_Unlock();
13109                 RSurf_DrawBatch();
13110         }
13111 }
13112
13113 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13114 {
13115         CHECKGLERROR
13116         RSurf_SetupDepthAndCulling();
13117         if (r_showsurfaces.integer)
13118         {
13119                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13120                 return;
13121         }
13122         switch (vid.renderpath)
13123         {
13124         case RENDERPATH_GL20:
13125         case RENDERPATH_CGGL:
13126         case RENDERPATH_D3D9:
13127         case RENDERPATH_D3D10:
13128         case RENDERPATH_D3D11:
13129                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13130                 break;
13131         case RENDERPATH_GL13:
13132                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13133                 break;
13134         case RENDERPATH_GL11:
13135                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13136                 break;
13137         }
13138         CHECKGLERROR
13139 }
13140
13141 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13142 {
13143         CHECKGLERROR
13144         RSurf_SetupDepthAndCulling();
13145         if (r_showsurfaces.integer)
13146         {
13147                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13148                 return;
13149         }
13150         switch (vid.renderpath)
13151         {
13152         case RENDERPATH_GL20:
13153         case RENDERPATH_CGGL:
13154         case RENDERPATH_D3D9:
13155         case RENDERPATH_D3D10:
13156         case RENDERPATH_D3D11:
13157                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13158                 break;
13159         case RENDERPATH_GL13:
13160                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13161                 break;
13162         case RENDERPATH_GL11:
13163                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13164                 break;
13165         }
13166         CHECKGLERROR
13167 }
13168
13169 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13170 {
13171         int i, j;
13172         int texturenumsurfaces, endsurface;
13173         texture_t *texture;
13174         const msurface_t *surface;
13175 #define MAXBATCH_TRANSPARENTSURFACES 256
13176         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13177
13178         // if the model is static it doesn't matter what value we give for
13179         // wantnormals and wanttangents, so this logic uses only rules applicable
13180         // to a model, knowing that they are meaningless otherwise
13181         if (ent == r_refdef.scene.worldentity)
13182                 RSurf_ActiveWorldEntity();
13183         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13184                 RSurf_ActiveModelEntity(ent, false, false, false);
13185         else
13186         {
13187                 switch (vid.renderpath)
13188                 {
13189                 case RENDERPATH_GL20:
13190                 case RENDERPATH_CGGL:
13191                 case RENDERPATH_D3D9:
13192                 case RENDERPATH_D3D10:
13193                 case RENDERPATH_D3D11:
13194                         RSurf_ActiveModelEntity(ent, true, true, false);
13195                         break;
13196                 case RENDERPATH_GL13:
13197                 case RENDERPATH_GL11:
13198                         RSurf_ActiveModelEntity(ent, true, false, false);
13199                         break;
13200                 }
13201         }
13202
13203         if (r_transparentdepthmasking.integer)
13204         {
13205                 qboolean setup = false;
13206                 for (i = 0;i < numsurfaces;i = j)
13207                 {
13208                         j = i + 1;
13209                         surface = rsurface.modelsurfaces + surfacelist[i];
13210                         texture = surface->texture;
13211                         rsurface.texture = R_GetCurrentTexture(texture);
13212                         rsurface.lightmaptexture = NULL;
13213                         rsurface.deluxemaptexture = NULL;
13214                         rsurface.uselightmaptexture = false;
13215                         // scan ahead until we find a different texture
13216                         endsurface = min(i + 1024, numsurfaces);
13217                         texturenumsurfaces = 0;
13218                         texturesurfacelist[texturenumsurfaces++] = surface;
13219                         for (;j < endsurface;j++)
13220                         {
13221                                 surface = rsurface.modelsurfaces + surfacelist[j];
13222                                 if (texture != surface->texture)
13223                                         break;
13224                                 texturesurfacelist[texturenumsurfaces++] = surface;
13225                         }
13226                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13227                                 continue;
13228                         // render the range of surfaces as depth
13229                         if (!setup)
13230                         {
13231                                 setup = true;
13232                                 GL_ColorMask(0,0,0,0);
13233                                 GL_Color(1,1,1,1);
13234                                 GL_DepthTest(true);
13235                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13236                                 GL_DepthMask(true);
13237                                 GL_AlphaTest(false);
13238 //                              R_Mesh_ResetTextureState();
13239                                 R_SetupShader_DepthOrShadow();
13240                         }
13241                         RSurf_SetupDepthAndCulling();
13242                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13243                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13244                         RSurf_DrawBatch();
13245                 }
13246                 if (setup)
13247                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13248         }
13249
13250         for (i = 0;i < numsurfaces;i = j)
13251         {
13252                 j = i + 1;
13253                 surface = rsurface.modelsurfaces + surfacelist[i];
13254                 texture = surface->texture;
13255                 rsurface.texture = R_GetCurrentTexture(texture);
13256                 // scan ahead until we find a different texture
13257                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13258                 texturenumsurfaces = 0;
13259                 texturesurfacelist[texturenumsurfaces++] = surface;
13260                 if(FAKELIGHT_ENABLED)
13261                 {
13262                         rsurface.lightmaptexture = NULL;
13263                         rsurface.deluxemaptexture = NULL;
13264                         rsurface.uselightmaptexture = false;
13265                         for (;j < endsurface;j++)
13266                         {
13267                                 surface = rsurface.modelsurfaces + surfacelist[j];
13268                                 if (texture != surface->texture)
13269                                         break;
13270                                 texturesurfacelist[texturenumsurfaces++] = surface;
13271                         }
13272                 }
13273                 else
13274                 {
13275                         rsurface.lightmaptexture = surface->lightmaptexture;
13276                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13277                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13278                         for (;j < endsurface;j++)
13279                         {
13280                                 surface = rsurface.modelsurfaces + surfacelist[j];
13281                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13282                                         break;
13283                                 texturesurfacelist[texturenumsurfaces++] = surface;
13284                         }
13285                 }
13286                 // render the range of surfaces
13287                 if (ent == r_refdef.scene.worldentity)
13288                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13289                 else
13290                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13291         }
13292         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13293         GL_AlphaTest(false);
13294 }
13295
13296 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13297 {
13298         // transparent surfaces get pushed off into the transparent queue
13299         int surfacelistindex;
13300         const msurface_t *surface;
13301         vec3_t tempcenter, center;
13302         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13303         {
13304                 surface = texturesurfacelist[surfacelistindex];
13305                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13306                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13307                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13308                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13309                 if (queueentity->transparent_offset) // transparent offset
13310                 {
13311                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13312                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13313                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13314                 }
13315                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13316         }
13317 }
13318
13319 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13320 {
13321         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13322                 return;
13323         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13324                 return;
13325         RSurf_SetupDepthAndCulling();
13326         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13327         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13328         RSurf_DrawBatch();
13329 }
13330
13331 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13332 {
13333         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13334         CHECKGLERROR
13335         if (depthonly)
13336                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13337         else if (prepass)
13338         {
13339                 if (!rsurface.texture->currentnumlayers)
13340                         return;
13341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13342                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13343                 else
13344                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13345         }
13346         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13347                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13348         else if (!rsurface.texture->currentnumlayers)
13349                 return;
13350         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13351         {
13352                 // in the deferred case, transparent surfaces were queued during prepass
13353                 if (!r_shadow_usingdeferredprepass)
13354                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13355         }
13356         else
13357         {
13358                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13359                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13360         }
13361         CHECKGLERROR
13362 }
13363
13364 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13365 {
13366         int i, j;
13367         texture_t *texture;
13368         // break the surface list down into batches by texture and use of lightmapping
13369         for (i = 0;i < numsurfaces;i = j)
13370         {
13371                 j = i + 1;
13372                 // texture is the base texture pointer, rsurface.texture is the
13373                 // current frame/skin the texture is directing us to use (for example
13374                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13375                 // use skin 1 instead)
13376                 texture = surfacelist[i]->texture;
13377                 rsurface.texture = R_GetCurrentTexture(texture);
13378                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13379                 {
13380                         // if this texture is not the kind we want, skip ahead to the next one
13381                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13382                                 ;
13383                         continue;
13384                 }
13385                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13386                 {
13387                         rsurface.lightmaptexture = NULL;
13388                         rsurface.deluxemaptexture = NULL;
13389                         rsurface.uselightmaptexture = false;
13390                         // simply scan ahead until we find a different texture or lightmap state
13391                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13392                                 ;
13393                 }
13394                 else
13395                 {
13396                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13397                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13398                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13399                         // simply scan ahead until we find a different texture or lightmap state
13400                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13401                                 ;
13402                 }
13403                 // render the range of surfaces
13404                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13405         }
13406 }
13407
13408 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13409 {
13410         CHECKGLERROR
13411         if (depthonly)
13412                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13413         else if (prepass)
13414         {
13415                 if (!rsurface.texture->currentnumlayers)
13416                         return;
13417                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13418                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13419                 else
13420                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13421         }
13422         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13423                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13424         else if (!rsurface.texture->currentnumlayers)
13425                 return;
13426         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13427         {
13428                 // in the deferred case, transparent surfaces were queued during prepass
13429                 if (!r_shadow_usingdeferredprepass)
13430                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13431         }
13432         else
13433         {
13434                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13435                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13436         }
13437         CHECKGLERROR
13438 }
13439
13440 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13441 {
13442         int i, j;
13443         texture_t *texture;
13444         // break the surface list down into batches by texture and use of lightmapping
13445         for (i = 0;i < numsurfaces;i = j)
13446         {
13447                 j = i + 1;
13448                 // texture is the base texture pointer, rsurface.texture is the
13449                 // current frame/skin the texture is directing us to use (for example
13450                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13451                 // use skin 1 instead)
13452                 texture = surfacelist[i]->texture;
13453                 rsurface.texture = R_GetCurrentTexture(texture);
13454                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13455                 {
13456                         // if this texture is not the kind we want, skip ahead to the next one
13457                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13458                                 ;
13459                         continue;
13460                 }
13461                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13462                 {
13463                         rsurface.lightmaptexture = NULL;
13464                         rsurface.deluxemaptexture = NULL;
13465                         rsurface.uselightmaptexture = false;
13466                         // simply scan ahead until we find a different texture or lightmap state
13467                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13468                                 ;
13469                 }
13470                 else
13471                 {
13472                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13473                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13474                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13475                         // simply scan ahead until we find a different texture or lightmap state
13476                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13477                                 ;
13478                 }
13479                 // render the range of surfaces
13480                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13481         }
13482 }
13483
13484 float locboxvertex3f[6*4*3] =
13485 {
13486         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13487         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13488         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13489         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13490         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13491         1,0,0, 0,0,0, 0,1,0, 1,1,0
13492 };
13493
13494 unsigned short locboxelements[6*2*3] =
13495 {
13496          0, 1, 2, 0, 2, 3,
13497          4, 5, 6, 4, 6, 7,
13498          8, 9,10, 8,10,11,
13499         12,13,14, 12,14,15,
13500         16,17,18, 16,18,19,
13501         20,21,22, 20,22,23
13502 };
13503
13504 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13505 {
13506         int i, j;
13507         cl_locnode_t *loc = (cl_locnode_t *)ent;
13508         vec3_t mins, size;
13509         float vertex3f[6*4*3];
13510         CHECKGLERROR
13511         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13512         GL_DepthMask(false);
13513         GL_DepthRange(0, 1);
13514         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13515         GL_DepthTest(true);
13516         GL_CullFace(GL_NONE);
13517         R_EntityMatrix(&identitymatrix);
13518
13519 //      R_Mesh_ResetTextureState();
13520
13521         i = surfacelist[0];
13522         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13523                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13524                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13525                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13526
13527         if (VectorCompare(loc->mins, loc->maxs))
13528         {
13529                 VectorSet(size, 2, 2, 2);
13530                 VectorMA(loc->mins, -0.5f, size, mins);
13531         }
13532         else
13533         {
13534                 VectorCopy(loc->mins, mins);
13535                 VectorSubtract(loc->maxs, loc->mins, size);
13536         }
13537
13538         for (i = 0;i < 6*4*3;)
13539                 for (j = 0;j < 3;j++, i++)
13540                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13541
13542         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13543         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13544         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13545 }
13546
13547 void R_DrawLocs(void)
13548 {
13549         int index;
13550         cl_locnode_t *loc, *nearestloc;
13551         vec3_t center;
13552         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13553         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13554         {
13555                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13556                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13557         }
13558 }
13559
13560 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13561 {
13562         if (decalsystem->decals)
13563                 Mem_Free(decalsystem->decals);
13564         memset(decalsystem, 0, sizeof(*decalsystem));
13565 }
13566
13567 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)
13568 {
13569         tridecal_t *decal;
13570         tridecal_t *decals;
13571         int i;
13572
13573         // expand or initialize the system
13574         if (decalsystem->maxdecals <= decalsystem->numdecals)
13575         {
13576                 decalsystem_t old = *decalsystem;
13577                 qboolean useshortelements;
13578                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13579                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13580                 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)));
13581                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13582                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13583                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13584                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13585                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13586                 if (decalsystem->numdecals)
13587                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13588                 if (old.decals)
13589                         Mem_Free(old.decals);
13590                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13591                         decalsystem->element3i[i] = i;
13592                 if (useshortelements)
13593                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13594                                 decalsystem->element3s[i] = i;
13595         }
13596
13597         // grab a decal and search for another free slot for the next one
13598         decals = decalsystem->decals;
13599         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13600         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13601                 ;
13602         decalsystem->freedecal = i;
13603         if (decalsystem->numdecals <= i)
13604                 decalsystem->numdecals = i + 1;
13605
13606         // initialize the decal
13607         decal->lived = 0;
13608         decal->triangleindex = triangleindex;
13609         decal->surfaceindex = surfaceindex;
13610         decal->decalsequence = decalsequence;
13611         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13612         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13613         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13614         decal->color4ub[0][3] = 255;
13615         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13616         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13617         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13618         decal->color4ub[1][3] = 255;
13619         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13620         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13621         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13622         decal->color4ub[2][3] = 255;
13623         decal->vertex3f[0][0] = v0[0];
13624         decal->vertex3f[0][1] = v0[1];
13625         decal->vertex3f[0][2] = v0[2];
13626         decal->vertex3f[1][0] = v1[0];
13627         decal->vertex3f[1][1] = v1[1];
13628         decal->vertex3f[1][2] = v1[2];
13629         decal->vertex3f[2][0] = v2[0];
13630         decal->vertex3f[2][1] = v2[1];
13631         decal->vertex3f[2][2] = v2[2];
13632         decal->texcoord2f[0][0] = t0[0];
13633         decal->texcoord2f[0][1] = t0[1];
13634         decal->texcoord2f[1][0] = t1[0];
13635         decal->texcoord2f[1][1] = t1[1];
13636         decal->texcoord2f[2][0] = t2[0];
13637         decal->texcoord2f[2][1] = t2[1];
13638 }
13639
13640 extern cvar_t cl_decals_bias;
13641 extern cvar_t cl_decals_models;
13642 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13643 // baseparms, parms, temps
13644 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)
13645 {
13646         int cornerindex;
13647         int index;
13648         float v[9][3];
13649         const float *vertex3f;
13650         int numpoints;
13651         float points[2][9][3];
13652         float temp[3];
13653         float tc[9][2];
13654         float f;
13655         float c[9][4];
13656         const int *e;
13657
13658         e = rsurface.modelelement3i + 3*triangleindex;
13659
13660         vertex3f = rsurface.modelvertex3f;
13661
13662         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13663         {
13664                 index = 3*e[cornerindex];
13665                 VectorCopy(vertex3f + index, v[cornerindex]);
13666         }
13667         // cull backfaces
13668         //TriangleNormal(v[0], v[1], v[2], normal);
13669         //if (DotProduct(normal, localnormal) < 0.0f)
13670         //      continue;
13671         // clip by each of the box planes formed from the projection matrix
13672         // if anything survives, we emit the decal
13673         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]);
13674         if (numpoints < 3)
13675                 return;
13676         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]);
13677         if (numpoints < 3)
13678                 return;
13679         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]);
13680         if (numpoints < 3)
13681                 return;
13682         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]);
13683         if (numpoints < 3)
13684                 return;
13685         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]);
13686         if (numpoints < 3)
13687                 return;
13688         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]);
13689         if (numpoints < 3)
13690                 return;
13691         // some part of the triangle survived, so we have to accept it...
13692         if (dynamic)
13693         {
13694                 // dynamic always uses the original triangle
13695                 numpoints = 3;
13696                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13697                 {
13698                         index = 3*e[cornerindex];
13699                         VectorCopy(vertex3f + index, v[cornerindex]);
13700                 }
13701         }
13702         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13703         {
13704                 // convert vertex positions to texcoords
13705                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13706                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13707                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13708                 // calculate distance fade from the projection origin
13709                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13710                 f = bound(0.0f, f, 1.0f);
13711                 c[cornerindex][0] = r * f;
13712                 c[cornerindex][1] = g * f;
13713                 c[cornerindex][2] = b * f;
13714                 c[cornerindex][3] = 1.0f;
13715                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13716         }
13717         if (dynamic)
13718                 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);
13719         else
13720                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13721                         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);
13722 }
13723 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)
13724 {
13725         matrix4x4_t projection;
13726         decalsystem_t *decalsystem;
13727         qboolean dynamic;
13728         dp_model_t *model;
13729         const msurface_t *surface;
13730         const msurface_t *surfaces;
13731         const int *surfacelist;
13732         const texture_t *texture;
13733         int numtriangles;
13734         int numsurfacelist;
13735         int surfacelistindex;
13736         int surfaceindex;
13737         int triangleindex;
13738         float localorigin[3];
13739         float localnormal[3];
13740         float localmins[3];
13741         float localmaxs[3];
13742         float localsize;
13743         //float normal[3];
13744         float planes[6][4];
13745         float angles[3];
13746         bih_t *bih;
13747         int bih_triangles_count;
13748         int bih_triangles[256];
13749         int bih_surfaces[256];
13750
13751         decalsystem = &ent->decalsystem;
13752         model = ent->model;
13753         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13754         {
13755                 R_DecalSystem_Reset(&ent->decalsystem);
13756                 return;
13757         }
13758
13759         if (!model->brush.data_leafs && !cl_decals_models.integer)
13760         {
13761                 if (decalsystem->model)
13762                         R_DecalSystem_Reset(decalsystem);
13763                 return;
13764         }
13765
13766         if (decalsystem->model != model)
13767                 R_DecalSystem_Reset(decalsystem);
13768         decalsystem->model = model;
13769
13770         RSurf_ActiveModelEntity(ent, false, false, false);
13771
13772         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13773         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13774         VectorNormalize(localnormal);
13775         localsize = worldsize*rsurface.inversematrixscale;
13776         localmins[0] = localorigin[0] - localsize;
13777         localmins[1] = localorigin[1] - localsize;
13778         localmins[2] = localorigin[2] - localsize;
13779         localmaxs[0] = localorigin[0] + localsize;
13780         localmaxs[1] = localorigin[1] + localsize;
13781         localmaxs[2] = localorigin[2] + localsize;
13782
13783         //VectorCopy(localnormal, planes[4]);
13784         //VectorVectors(planes[4], planes[2], planes[0]);
13785         AnglesFromVectors(angles, localnormal, NULL, false);
13786         AngleVectors(angles, planes[0], planes[2], planes[4]);
13787         VectorNegate(planes[0], planes[1]);
13788         VectorNegate(planes[2], planes[3]);
13789         VectorNegate(planes[4], planes[5]);
13790         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13791         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13792         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13793         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13794         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13795         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13796
13797 #if 1
13798 // works
13799 {
13800         matrix4x4_t forwardprojection;
13801         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13802         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13803 }
13804 #else
13805 // broken
13806 {
13807         float projectionvector[4][3];
13808         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13809         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13810         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13811         projectionvector[0][0] = planes[0][0] * ilocalsize;
13812         projectionvector[0][1] = planes[1][0] * ilocalsize;
13813         projectionvector[0][2] = planes[2][0] * ilocalsize;
13814         projectionvector[1][0] = planes[0][1] * ilocalsize;
13815         projectionvector[1][1] = planes[1][1] * ilocalsize;
13816         projectionvector[1][2] = planes[2][1] * ilocalsize;
13817         projectionvector[2][0] = planes[0][2] * ilocalsize;
13818         projectionvector[2][1] = planes[1][2] * ilocalsize;
13819         projectionvector[2][2] = planes[2][2] * ilocalsize;
13820         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13821         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13822         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13823         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13824 }
13825 #endif
13826
13827         dynamic = model->surfmesh.isanimated;
13828         numsurfacelist = model->nummodelsurfaces;
13829         surfacelist = model->sortedmodelsurfaces;
13830         surfaces = model->data_surfaces;
13831
13832         bih = NULL;
13833         bih_triangles_count = -1;
13834         if(!dynamic)
13835         {
13836                 if(model->render_bih.numleafs)
13837                         bih = &model->render_bih;
13838                 else if(model->collision_bih.numleafs)
13839                         bih = &model->collision_bih;
13840         }
13841         if(bih)
13842                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13843         if(bih_triangles_count == 0)
13844                 return;
13845         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13846                 return;
13847         if(bih_triangles_count > 0)
13848         {
13849                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13850                 {
13851                         surfaceindex = bih_surfaces[triangleindex];
13852                         surface = surfaces + surfaceindex;
13853                         texture = surface->texture;
13854                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13855                                 continue;
13856                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13857                                 continue;
13858                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13859                 }
13860         }
13861         else
13862         {
13863                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13864                 {
13865                         surfaceindex = surfacelist[surfacelistindex];
13866                         surface = surfaces + surfaceindex;
13867                         // check cull box first because it rejects more than any other check
13868                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13869                                 continue;
13870                         // skip transparent surfaces
13871                         texture = surface->texture;
13872                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13873                                 continue;
13874                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13875                                 continue;
13876                         numtriangles = surface->num_triangles;
13877                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13878                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13879                 }
13880         }
13881 }
13882
13883 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13884 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)
13885 {
13886         int renderentityindex;
13887         float worldmins[3];
13888         float worldmaxs[3];
13889         entity_render_t *ent;
13890
13891         if (!cl_decals_newsystem.integer)
13892                 return;
13893
13894         worldmins[0] = worldorigin[0] - worldsize;
13895         worldmins[1] = worldorigin[1] - worldsize;
13896         worldmins[2] = worldorigin[2] - worldsize;
13897         worldmaxs[0] = worldorigin[0] + worldsize;
13898         worldmaxs[1] = worldorigin[1] + worldsize;
13899         worldmaxs[2] = worldorigin[2] + worldsize;
13900
13901         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13902
13903         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13904         {
13905                 ent = r_refdef.scene.entities[renderentityindex];
13906                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13907                         continue;
13908
13909                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13910         }
13911 }
13912
13913 typedef struct r_decalsystem_splatqueue_s
13914 {
13915         vec3_t worldorigin;
13916         vec3_t worldnormal;
13917         float color[4];
13918         float tcrange[4];
13919         float worldsize;
13920         int decalsequence;
13921 }
13922 r_decalsystem_splatqueue_t;
13923
13924 int r_decalsystem_numqueued = 0;
13925 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13926
13927 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)
13928 {
13929         r_decalsystem_splatqueue_t *queue;
13930
13931         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13932                 return;
13933
13934         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13935         VectorCopy(worldorigin, queue->worldorigin);
13936         VectorCopy(worldnormal, queue->worldnormal);
13937         Vector4Set(queue->color, r, g, b, a);
13938         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13939         queue->worldsize = worldsize;
13940         queue->decalsequence = cl.decalsequence++;
13941 }
13942
13943 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13944 {
13945         int i;
13946         r_decalsystem_splatqueue_t *queue;
13947
13948         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13949                 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);
13950         r_decalsystem_numqueued = 0;
13951 }
13952
13953 extern cvar_t cl_decals_max;
13954 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13955 {
13956         int i;
13957         decalsystem_t *decalsystem = &ent->decalsystem;
13958         int numdecals;
13959         int killsequence;
13960         tridecal_t *decal;
13961         float frametime;
13962         float lifetime;
13963
13964         if (!decalsystem->numdecals)
13965                 return;
13966
13967         if (r_showsurfaces.integer)
13968                 return;
13969
13970         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13971         {
13972                 R_DecalSystem_Reset(decalsystem);
13973                 return;
13974         }
13975
13976         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13977         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13978
13979         if (decalsystem->lastupdatetime)
13980                 frametime = (cl.time - decalsystem->lastupdatetime);
13981         else
13982                 frametime = 0;
13983         decalsystem->lastupdatetime = cl.time;
13984         decal = decalsystem->decals;
13985         numdecals = decalsystem->numdecals;
13986
13987         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13988         {
13989                 if (decal->color4ub[0][3])
13990                 {
13991                         decal->lived += frametime;
13992                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13993                         {
13994                                 memset(decal, 0, sizeof(*decal));
13995                                 if (decalsystem->freedecal > i)
13996                                         decalsystem->freedecal = i;
13997                         }
13998                 }
13999         }
14000         decal = decalsystem->decals;
14001         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14002                 numdecals--;
14003
14004         // collapse the array by shuffling the tail decals into the gaps
14005         for (;;)
14006         {
14007                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14008                         decalsystem->freedecal++;
14009                 if (decalsystem->freedecal == numdecals)
14010                         break;
14011                 decal[decalsystem->freedecal] = decal[--numdecals];
14012         }
14013
14014         decalsystem->numdecals = numdecals;
14015
14016         if (numdecals <= 0)
14017         {
14018                 // if there are no decals left, reset decalsystem
14019                 R_DecalSystem_Reset(decalsystem);
14020         }
14021 }
14022
14023 extern skinframe_t *decalskinframe;
14024 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14025 {
14026         int i;
14027         decalsystem_t *decalsystem = &ent->decalsystem;
14028         int numdecals;
14029         tridecal_t *decal;
14030         float faderate;
14031         float alpha;
14032         float *v3f;
14033         float *c4f;
14034         float *t2f;
14035         const int *e;
14036         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14037         int numtris = 0;
14038
14039         numdecals = decalsystem->numdecals;
14040         if (!numdecals)
14041                 return;
14042
14043         if (r_showsurfaces.integer)
14044                 return;
14045
14046         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14047         {
14048                 R_DecalSystem_Reset(decalsystem);
14049                 return;
14050         }
14051
14052         // if the model is static it doesn't matter what value we give for
14053         // wantnormals and wanttangents, so this logic uses only rules applicable
14054         // to a model, knowing that they are meaningless otherwise
14055         if (ent == r_refdef.scene.worldentity)
14056                 RSurf_ActiveWorldEntity();
14057         else
14058                 RSurf_ActiveModelEntity(ent, false, false, false);
14059
14060         decalsystem->lastupdatetime = cl.time;
14061         decal = decalsystem->decals;
14062
14063         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14064
14065         // update vertex positions for animated models
14066         v3f = decalsystem->vertex3f;
14067         c4f = decalsystem->color4f;
14068         t2f = decalsystem->texcoord2f;
14069         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14070         {
14071                 if (!decal->color4ub[0][3])
14072                         continue;
14073
14074                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14075                         continue;
14076
14077                 // update color values for fading decals
14078                 if (decal->lived >= cl_decals_time.value)
14079                 {
14080                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14081                         alpha *= (1.0f/255.0f);
14082                 }
14083                 else
14084                         alpha = 1.0f/255.0f;
14085
14086                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14087                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14088                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14089                 c4f[ 3] = 1;
14090                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14091                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14092                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14093                 c4f[ 7] = 1;
14094                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14095                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14096                 c4f[10] = decal->color4ub[2][2] * alpha;
14097                 c4f[11] = 1;
14098
14099                 t2f[0] = decal->texcoord2f[0][0];
14100                 t2f[1] = decal->texcoord2f[0][1];
14101                 t2f[2] = decal->texcoord2f[1][0];
14102                 t2f[3] = decal->texcoord2f[1][1];
14103                 t2f[4] = decal->texcoord2f[2][0];
14104                 t2f[5] = decal->texcoord2f[2][1];
14105
14106                 // update vertex positions for animated models
14107                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14108                 {
14109                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14110                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14111                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14112                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14113                 }
14114                 else
14115                 {
14116                         VectorCopy(decal->vertex3f[0], v3f);
14117                         VectorCopy(decal->vertex3f[1], v3f + 3);
14118                         VectorCopy(decal->vertex3f[2], v3f + 6);
14119                 }
14120
14121                 if (r_refdef.fogenabled)
14122                 {
14123                         alpha = RSurf_FogVertex(v3f);
14124                         VectorScale(c4f, alpha, c4f);
14125                         alpha = RSurf_FogVertex(v3f + 3);
14126                         VectorScale(c4f + 4, alpha, c4f + 4);
14127                         alpha = RSurf_FogVertex(v3f + 6);
14128                         VectorScale(c4f + 8, alpha, c4f + 8);
14129                 }
14130
14131                 v3f += 9;
14132                 c4f += 12;
14133                 t2f += 6;
14134                 numtris++;
14135         }
14136
14137         if (numtris > 0)
14138         {
14139                 r_refdef.stats.drawndecals += numtris;
14140
14141                 // now render the decals all at once
14142                 // (this assumes they all use one particle font texture!)
14143                 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);
14144 //              R_Mesh_ResetTextureState();
14145                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14146                 GL_DepthMask(false);
14147                 GL_DepthRange(0, 1);
14148                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14149                 GL_DepthTest(true);
14150                 GL_CullFace(GL_NONE);
14151                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14152                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14153                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14154         }
14155 }
14156
14157 static void R_DrawModelDecals(void)
14158 {
14159         int i, numdecals;
14160
14161         // fade faster when there are too many decals
14162         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14163         for (i = 0;i < r_refdef.scene.numentities;i++)
14164                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14165
14166         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14167         for (i = 0;i < r_refdef.scene.numentities;i++)
14168                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14169                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14170
14171         R_DecalSystem_ApplySplatEntitiesQueue();
14172
14173         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14174         for (i = 0;i < r_refdef.scene.numentities;i++)
14175                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14176
14177         r_refdef.stats.totaldecals += numdecals;
14178
14179         if (r_showsurfaces.integer)
14180                 return;
14181
14182         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14183
14184         for (i = 0;i < r_refdef.scene.numentities;i++)
14185         {
14186                 if (!r_refdef.viewcache.entityvisible[i])
14187                         continue;
14188                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14189                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14190         }
14191 }
14192
14193 extern cvar_t mod_collision_bih;
14194 void R_DrawDebugModel(void)
14195 {
14196         entity_render_t *ent = rsurface.entity;
14197         int i, j, k, l, flagsmask;
14198         const msurface_t *surface;
14199         dp_model_t *model = ent->model;
14200         vec3_t v;
14201
14202         switch(vid.renderpath)
14203         {
14204         case RENDERPATH_GL11:
14205         case RENDERPATH_GL13:
14206         case RENDERPATH_GL20:
14207         case RENDERPATH_CGGL:
14208                 break;
14209         case RENDERPATH_D3D9:
14210                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14211                 return;
14212         case RENDERPATH_D3D10:
14213                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14214                 return;
14215         case RENDERPATH_D3D11:
14216                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14217                 return;
14218         }
14219
14220         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14221
14222 //      R_Mesh_ResetTextureState();
14223         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14224         GL_DepthRange(0, 1);
14225         GL_DepthTest(!r_showdisabledepthtest.integer);
14226         GL_DepthMask(false);
14227         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14228
14229         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14230         {
14231                 int triangleindex;
14232                 int bihleafindex;
14233                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14234                 const q3mbrush_t *brush;
14235                 const bih_t *bih = &model->collision_bih;
14236                 const bih_leaf_t *bihleaf;
14237                 float vertex3f[3][3];
14238                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14239                 cullbox = false;
14240                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14241                 {
14242                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14243                                 continue;
14244                         switch (bihleaf->type)
14245                         {
14246                         case BIH_BRUSH:
14247                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14248                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14249                                 {
14250                                         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);
14251                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14252                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14253                                 }
14254                                 break;
14255                         case BIH_COLLISIONTRIANGLE:
14256                                 triangleindex = bihleaf->itemindex;
14257                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14258                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14259                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14260                                 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);
14261                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14262                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14263                                 break;
14264                         case BIH_RENDERTRIANGLE:
14265                                 triangleindex = bihleaf->itemindex;
14266                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14267                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14268                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14269                                 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);
14270                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14271                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14272                                 break;
14273                         }
14274                 }
14275         }
14276
14277         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14278
14279         if (r_showtris.integer || (r_shownormals.value != 0))
14280         {
14281                 if (r_showdisabledepthtest.integer)
14282                 {
14283                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14284                         GL_DepthMask(false);
14285                 }
14286                 else
14287                 {
14288                         GL_BlendFunc(GL_ONE, GL_ZERO);
14289                         GL_DepthMask(true);
14290                 }
14291                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14292                 {
14293                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14294                                 continue;
14295                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14296                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14297                         {
14298                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14299                                 if (r_showtris.value > 0)
14300                                 {
14301                                         if (!rsurface.texture->currentlayers->depthmask)
14302                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14303                                         else if (ent == r_refdef.scene.worldentity)
14304                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14305                                         else
14306                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14307                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14308                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14309                                         RSurf_DrawBatch();
14310                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14311                                         CHECKGLERROR
14312                                 }
14313                                 if (r_shownormals.value < 0)
14314                                 {
14315                                         qglBegin(GL_LINES);
14316                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14317                                         {
14318                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14319                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14320                                                 qglVertex3f(v[0], v[1], v[2]);
14321                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14322                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14323                                                 qglVertex3f(v[0], v[1], v[2]);
14324                                         }
14325                                         qglEnd();
14326                                         CHECKGLERROR
14327                                 }
14328                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14329                                 {
14330                                         qglBegin(GL_LINES);
14331                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14332                                         {
14333                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14334                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14335                                                 qglVertex3f(v[0], v[1], v[2]);
14336                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14337                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14338                                                 qglVertex3f(v[0], v[1], v[2]);
14339                                         }
14340                                         qglEnd();
14341                                         CHECKGLERROR
14342                                         qglBegin(GL_LINES);
14343                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14344                                         {
14345                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14346                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14347                                                 qglVertex3f(v[0], v[1], v[2]);
14348                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14349                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14350                                                 qglVertex3f(v[0], v[1], v[2]);
14351                                         }
14352                                         qglEnd();
14353                                         CHECKGLERROR
14354                                         qglBegin(GL_LINES);
14355                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14356                                         {
14357                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14358                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14359                                                 qglVertex3f(v[0], v[1], v[2]);
14360                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14361                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14362                                                 qglVertex3f(v[0], v[1], v[2]);
14363                                         }
14364                                         qglEnd();
14365                                         CHECKGLERROR
14366                                 }
14367                         }
14368                 }
14369                 rsurface.texture = NULL;
14370         }
14371 }
14372
14373 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14374 int r_maxsurfacelist = 0;
14375 const msurface_t **r_surfacelist = NULL;
14376 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14377 {
14378         int i, j, endj, flagsmask;
14379         dp_model_t *model = r_refdef.scene.worldmodel;
14380         msurface_t *surfaces;
14381         unsigned char *update;
14382         int numsurfacelist = 0;
14383         if (model == NULL)
14384                 return;
14385
14386         if (r_maxsurfacelist < model->num_surfaces)
14387         {
14388                 r_maxsurfacelist = model->num_surfaces;
14389                 if (r_surfacelist)
14390                         Mem_Free((msurface_t**)r_surfacelist);
14391                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14392         }
14393
14394         RSurf_ActiveWorldEntity();
14395
14396         surfaces = model->data_surfaces;
14397         update = model->brushq1.lightmapupdateflags;
14398
14399         // update light styles on this submodel
14400         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14401         {
14402                 model_brush_lightstyleinfo_t *style;
14403                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14404                 {
14405                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14406                         {
14407                                 int *list = style->surfacelist;
14408                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14409                                 for (j = 0;j < style->numsurfaces;j++)
14410                                         update[list[j]] = true;
14411                         }
14412                 }
14413         }
14414
14415         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14416
14417         if (debug)
14418         {
14419                 R_DrawDebugModel();
14420                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14421                 return;
14422         }
14423
14424         rsurface.lightmaptexture = NULL;
14425         rsurface.deluxemaptexture = NULL;
14426         rsurface.uselightmaptexture = false;
14427         rsurface.texture = NULL;
14428         rsurface.rtlight = NULL;
14429         numsurfacelist = 0;
14430         // add visible surfaces to draw list
14431         for (i = 0;i < model->nummodelsurfaces;i++)
14432         {
14433                 j = model->sortedmodelsurfaces[i];
14434                 if (r_refdef.viewcache.world_surfacevisible[j])
14435                         r_surfacelist[numsurfacelist++] = surfaces + j;
14436         }
14437         // update lightmaps if needed
14438         if (model->brushq1.firstrender)
14439         {
14440                 model->brushq1.firstrender = false;
14441                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14442                         if (update[j])
14443                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14444         }
14445         else if (update)
14446         {
14447                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14448                         if (r_refdef.viewcache.world_surfacevisible[j])
14449                                 if (update[j])
14450                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14451         }
14452         // don't do anything if there were no surfaces
14453         if (!numsurfacelist)
14454         {
14455                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14456                 return;
14457         }
14458         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14459         GL_AlphaTest(false);
14460
14461         // add to stats if desired
14462         if (r_speeds.integer && !skysurfaces && !depthonly)
14463         {
14464                 r_refdef.stats.world_surfaces += numsurfacelist;
14465                 for (j = 0;j < numsurfacelist;j++)
14466                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14467         }
14468
14469         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14470 }
14471
14472 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14473 {
14474         int i, j, endj, flagsmask;
14475         dp_model_t *model = ent->model;
14476         msurface_t *surfaces;
14477         unsigned char *update;
14478         int numsurfacelist = 0;
14479         if (model == NULL)
14480                 return;
14481
14482         if (r_maxsurfacelist < model->num_surfaces)
14483         {
14484                 r_maxsurfacelist = model->num_surfaces;
14485                 if (r_surfacelist)
14486                         Mem_Free((msurface_t **)r_surfacelist);
14487                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14488         }
14489
14490         // if the model is static it doesn't matter what value we give for
14491         // wantnormals and wanttangents, so this logic uses only rules applicable
14492         // to a model, knowing that they are meaningless otherwise
14493         if (ent == r_refdef.scene.worldentity)
14494                 RSurf_ActiveWorldEntity();
14495         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14496                 RSurf_ActiveModelEntity(ent, false, false, false);
14497         else if (prepass)
14498                 RSurf_ActiveModelEntity(ent, true, true, true);
14499         else if (depthonly)
14500         {
14501                 switch (vid.renderpath)
14502                 {
14503                 case RENDERPATH_GL20:
14504                 case RENDERPATH_CGGL:
14505                 case RENDERPATH_D3D9:
14506                 case RENDERPATH_D3D10:
14507                 case RENDERPATH_D3D11:
14508                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14509                         break;
14510                 case RENDERPATH_GL13:
14511                 case RENDERPATH_GL11:
14512                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14513                         break;
14514                 }
14515         }
14516         else
14517         {
14518                 switch (vid.renderpath)
14519                 {
14520                 case RENDERPATH_GL20:
14521                 case RENDERPATH_CGGL:
14522                 case RENDERPATH_D3D9:
14523                 case RENDERPATH_D3D10:
14524                 case RENDERPATH_D3D11:
14525                         RSurf_ActiveModelEntity(ent, true, true, false);
14526                         break;
14527                 case RENDERPATH_GL13:
14528                 case RENDERPATH_GL11:
14529                         RSurf_ActiveModelEntity(ent, true, false, false);
14530                         break;
14531                 }
14532         }
14533
14534         surfaces = model->data_surfaces;
14535         update = model->brushq1.lightmapupdateflags;
14536
14537         // update light styles
14538         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14539         {
14540                 model_brush_lightstyleinfo_t *style;
14541                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14542                 {
14543                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14544                         {
14545                                 int *list = style->surfacelist;
14546                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14547                                 for (j = 0;j < style->numsurfaces;j++)
14548                                         update[list[j]] = true;
14549                         }
14550                 }
14551         }
14552
14553         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14554
14555         if (debug)
14556         {
14557                 R_DrawDebugModel();
14558                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14559                 return;
14560         }
14561
14562         rsurface.lightmaptexture = NULL;
14563         rsurface.deluxemaptexture = NULL;
14564         rsurface.uselightmaptexture = false;
14565         rsurface.texture = NULL;
14566         rsurface.rtlight = NULL;
14567         numsurfacelist = 0;
14568         // add visible surfaces to draw list
14569         for (i = 0;i < model->nummodelsurfaces;i++)
14570                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14571         // don't do anything if there were no surfaces
14572         if (!numsurfacelist)
14573         {
14574                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14575                 return;
14576         }
14577         // update lightmaps if needed
14578         if (update)
14579         {
14580                 int updated = 0;
14581                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14582                 {
14583                         if (update[j])
14584                         {
14585                                 updated++;
14586                                 R_BuildLightMap(ent, surfaces + j);
14587                         }
14588                 }
14589         }
14590         if (update)
14591                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14592                         if (update[j])
14593                                 R_BuildLightMap(ent, surfaces + j);
14594         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14595         GL_AlphaTest(false);
14596
14597         // add to stats if desired
14598         if (r_speeds.integer && !skysurfaces && !depthonly)
14599         {
14600                 r_refdef.stats.entities_surfaces += numsurfacelist;
14601                 for (j = 0;j < numsurfacelist;j++)
14602                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14603         }
14604
14605         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14606 }
14607
14608 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14609 {
14610         static texture_t texture;
14611         static msurface_t surface;
14612         const msurface_t *surfacelist = &surface;
14613
14614         // fake enough texture and surface state to render this geometry
14615
14616         texture.update_lastrenderframe = -1; // regenerate this texture
14617         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14618         texture.currentskinframe = skinframe;
14619         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14620         texture.offsetmapping = OFFSETMAPPING_OFF;
14621         texture.offsetscale = 1;
14622         texture.specularscalemod = 1;
14623         texture.specularpowermod = 1;
14624
14625         surface.texture = &texture;
14626         surface.num_triangles = numtriangles;
14627         surface.num_firsttriangle = firsttriangle;
14628         surface.num_vertices = numvertices;
14629         surface.num_firstvertex = firstvertex;
14630
14631         // now render it
14632         rsurface.texture = R_GetCurrentTexture(surface.texture);
14633         rsurface.lightmaptexture = NULL;
14634         rsurface.deluxemaptexture = NULL;
14635         rsurface.uselightmaptexture = false;
14636         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14637 }
14638
14639 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)
14640 {
14641         static msurface_t surface;
14642         const msurface_t *surfacelist = &surface;
14643
14644         // fake enough texture and surface state to render this geometry
14645         surface.texture = texture;
14646         surface.num_triangles = numtriangles;
14647         surface.num_firsttriangle = firsttriangle;
14648         surface.num_vertices = numvertices;
14649         surface.num_firstvertex = firstvertex;
14650
14651         // now render it
14652         rsurface.texture = R_GetCurrentTexture(surface.texture);
14653         rsurface.lightmaptexture = NULL;
14654         rsurface.deluxemaptexture = NULL;
14655         rsurface.uselightmaptexture = false;
14656         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14657 }