]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a crash with tcmod turbulent where it was not requesting texcoords
[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", "0.5", "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 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5279 {
5280         // a blendfunc allows colormod if:
5281         // a) it can never keep the destination pixel invariant, or
5282         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5283         // this is to prevent unintended side effects from colormod
5284
5285         // in formulas:
5286         // IF there is a (s, sa) for which for all (d, da),
5287         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5288         // THEN, for this (s, sa) and all (colormod, d, da):
5289         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5290         // OBVIOUSLY, this means that
5291         //   s*colormod * src(s*colormod, d, sa, da) = 0
5292         //   dst(s*colormod, d, sa, da)              = 1
5293
5294         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5295
5296         // main condition to leave dst color invariant:
5297         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5298         //   src == GL_ZERO:
5299         //     s * 0 + d * dst(s, d, sa, da) == d
5300         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301         //       => colormod is a problem for GL_SRC_COLOR only
5302         //   src == GL_ONE:
5303         //     s + d * dst(s, d, sa, da) == d
5304         //       => s == 0
5305         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306         //       => colormod is never problematic for these
5307         //   src == GL_SRC_COLOR:
5308         //     s*s + d * dst(s, d, sa, da) == d
5309         //       => s == 0
5310         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod is never problematic for these
5312         //   src == GL_ONE_MINUS_SRC_COLOR:
5313         //     s*(1-s) + d * dst(s, d, sa, da) == d
5314         //       => s == 0 or s == 1
5315         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is a problem for GL_SRC_COLOR only
5317         //   src == GL_DST_COLOR
5318         //     s*d + d * dst(s, d, sa, da) == d
5319         //       => s == 1
5320         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5321         //       => colormod is always a problem
5322         //     or
5323         //       => s == 0
5324         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5325         //       => colormod is never problematic for these
5326         //       => BUT, we do not know s! We must assume it is problematic
5327         //       then... except in GL_ONE case, where we know all invariant
5328         //       cases are fine
5329         //   src == GL_ONE_MINUS_DST_COLOR
5330         //     s*(1-d) + d * dst(s, d, sa, da) == d
5331         //       => s == 0 (1-d is impossible to handle for our desired result)
5332         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333         //       => colormod is never problematic for these
5334         //   src == GL_SRC_ALPHA
5335         //     s*sa + d * dst(s, d, sa, da) == d
5336         //       => s == 0, or sa == 0
5337         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338         //       => colormod breaks in the case GL_SRC_COLOR only
5339         //   src == GL_ONE_MINUS_SRC_ALPHA
5340         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5341         //       => s == 0, or sa == 1
5342         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5343         //       => colormod breaks in the case GL_SRC_COLOR only
5344         //   src == GL_DST_ALPHA
5345         //     s*da + d * dst(s, d, sa, da) == d
5346         //       => s == 0
5347         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5348         //       => colormod is never problematic for these
5349
5350         switch(src)
5351         {
5352                 case GL_ZERO:
5353                 case GL_ONE_MINUS_SRC_COLOR:
5354                 case GL_SRC_ALPHA:
5355                 case GL_ONE_MINUS_SRC_ALPHA:
5356                         if(dst == GL_SRC_COLOR)
5357                                 return false;
5358                         return true;
5359                 case GL_ONE:
5360                 case GL_SRC_COLOR:
5361                 case GL_ONE_MINUS_DST_COLOR:
5362                 case GL_DST_ALPHA:
5363                 case GL_ONE_MINUS_DST_ALPHA:
5364                         return true;
5365                 case GL_DST_COLOR:
5366                         if(dst == GL_ONE)
5367                                 return true;
5368                         return false;
5369                 default:
5370                         return false;
5371         }
5372 }
5373 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5374 {
5375         // select a permutation of the lighting shader appropriate to this
5376         // combination of texture, entity, light source, and fogging, only use the
5377         // minimum features necessary to avoid wasting rendering time in the
5378         // fragment shader on features that are not being used
5379         unsigned int permutation = 0;
5380         unsigned int mode = 0;
5381         qboolean allow_colormod;
5382         static float dummy_colormod[3] = {1, 1, 1};
5383         float *colormod = rsurface.colormod;
5384         float m16f[16];
5385         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5386         if (rsurfacepass == RSURFPASS_BACKGROUND)
5387         {
5388                 // distorted background
5389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5390                 {
5391                         mode = SHADERMODE_WATER;
5392                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5393                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5394                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5395                         {
5396                                 // this is the right thing to do for wateralpha
5397                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5398                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5399                         }
5400                         else
5401                         {
5402                                 // this is the right thing to do for entity alpha
5403                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5404                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5405                         }
5406                 }
5407                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5408                 {
5409                         mode = SHADERMODE_REFRACTION;
5410                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5411                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5412                 }
5413                 else
5414                 {
5415                         mode = SHADERMODE_GENERIC;
5416                         permutation |= SHADERPERMUTATION_DIFFUSE;
5417                         GL_BlendFunc(GL_ONE, GL_ZERO);
5418                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5419                 }
5420                 GL_AlphaTest(false);
5421         }
5422         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5423         {
5424                 if (r_glsl_offsetmapping.integer)
5425                 {
5426                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5427                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5428                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5429                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5430                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5431                         {
5432                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5433                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5434                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5435                         }
5436                 }
5437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5438                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5440                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5441                 // normalmap (deferred prepass), may use alpha test on diffuse
5442                 mode = SHADERMODE_DEFERREDGEOMETRY;
5443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5444                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5445                 GL_AlphaTest(false);
5446                 GL_BlendFunc(GL_ONE, GL_ZERO);
5447                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5448         }
5449         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5450         {
5451                 if (r_glsl_offsetmapping.integer)
5452                 {
5453                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5454                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5455                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5456                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5457                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5458                         {
5459                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5460                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5461                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5462                         }
5463                 }
5464                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5465                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5466                 // light source
5467                 mode = SHADERMODE_LIGHTSOURCE;
5468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5469                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5470                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5471                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5472                 if (diffusescale > 0)
5473                         permutation |= SHADERPERMUTATION_DIFFUSE;
5474                 if (specularscale > 0)
5475                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5476                 if (r_refdef.fogenabled)
5477                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5478                 if (rsurface.texture->colormapping)
5479                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5480                 if (r_shadow_usingshadowmap2d)
5481                 {
5482                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5483                         if(r_shadow_shadowmapvsdct)
5484                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5485
5486                         if (r_shadow_shadowmapsampler)
5487                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5488                         if (r_shadow_shadowmappcf > 1)
5489                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5490                         else if (r_shadow_shadowmappcf)
5491                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5492                 }
5493                 if (rsurface.texture->reflectmasktexture)
5494                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5495                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5496                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5497                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5498         }
5499         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5500         {
5501                 if (r_glsl_offsetmapping.integer)
5502                 {
5503                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5504                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5505                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5506                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5507                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5508                         {
5509                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5510                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5511                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5512                         }
5513                 }
5514                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5515                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5516                 // unshaded geometry (fullbright or ambient model lighting)
5517                 mode = SHADERMODE_FLATCOLOR;
5518                 ambientscale = diffusescale = specularscale = 0;
5519                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5520                         permutation |= SHADERPERMUTATION_GLOW;
5521                 if (r_refdef.fogenabled)
5522                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5523                 if (rsurface.texture->colormapping)
5524                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5525                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5526                 {
5527                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5528                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5529
5530                         if (r_shadow_shadowmapsampler)
5531                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5532                         if (r_shadow_shadowmappcf > 1)
5533                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5534                         else if (r_shadow_shadowmappcf)
5535                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5536                 }
5537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5538                         permutation |= SHADERPERMUTATION_REFLECTION;
5539                 if (rsurface.texture->reflectmasktexture)
5540                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5541                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5542                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5543                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5544         }
5545         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5546         {
5547                 if (r_glsl_offsetmapping.integer)
5548                 {
5549                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5550                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5551                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5552                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5553                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5554                         {
5555                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5556                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5557                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5558                         }
5559                 }
5560                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5561                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5562                 // directional model lighting
5563                 mode = SHADERMODE_LIGHTDIRECTION;
5564                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5565                         permutation |= SHADERPERMUTATION_GLOW;
5566                 permutation |= SHADERPERMUTATION_DIFFUSE;
5567                 if (specularscale > 0)
5568                         permutation |= SHADERPERMUTATION_SPECULAR;
5569                 if (r_refdef.fogenabled)
5570                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5571                 if (rsurface.texture->colormapping)
5572                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5573                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5574                 {
5575                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5576                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5577
5578                         if (r_shadow_shadowmapsampler)
5579                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5580                         if (r_shadow_shadowmappcf > 1)
5581                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5582                         else if (r_shadow_shadowmappcf)
5583                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5584                 }
5585                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5586                         permutation |= SHADERPERMUTATION_REFLECTION;
5587                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5588                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5589                 if (rsurface.texture->reflectmasktexture)
5590                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5591                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5592                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5593                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5594         }
5595         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5596         {
5597                 if (r_glsl_offsetmapping.integer)
5598                 {
5599                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5600                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5601                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5602                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5603                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5604                         {
5605                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5606                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5607                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5608                         }
5609                 }
5610                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5611                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5612                 // ambient model lighting
5613                 mode = SHADERMODE_LIGHTDIRECTION;
5614                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5615                         permutation |= SHADERPERMUTATION_GLOW;
5616                 if (r_refdef.fogenabled)
5617                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5618                 if (rsurface.texture->colormapping)
5619                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5620                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5621                 {
5622                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5623                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5624
5625                         if (r_shadow_shadowmapsampler)
5626                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5627                         if (r_shadow_shadowmappcf > 1)
5628                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5629                         else if (r_shadow_shadowmappcf)
5630                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5631                 }
5632                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5633                         permutation |= SHADERPERMUTATION_REFLECTION;
5634                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5635                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5636                 if (rsurface.texture->reflectmasktexture)
5637                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5638                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5639                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5640                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5641         }
5642         else
5643         {
5644                 if (r_glsl_offsetmapping.integer)
5645                 {
5646                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5647                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5648                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5649                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5650                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5651                         {
5652                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5653                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5654                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5655                         }
5656                 }
5657                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5658                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5659                 // lightmapped wall
5660                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5661                         permutation |= SHADERPERMUTATION_GLOW;
5662                 if (r_refdef.fogenabled)
5663                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5664                 if (rsurface.texture->colormapping)
5665                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5666                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5667                 {
5668                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5669                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5670
5671                         if (r_shadow_shadowmapsampler)
5672                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5673                         if (r_shadow_shadowmappcf > 1)
5674                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5675                         else if (r_shadow_shadowmappcf)
5676                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5677                 }
5678                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5679                         permutation |= SHADERPERMUTATION_REFLECTION;
5680                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5681                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5682                 if (rsurface.texture->reflectmasktexture)
5683                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5684                 if (FAKELIGHT_ENABLED)
5685                 {
5686                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5687                         mode = SHADERMODE_FAKELIGHT;
5688                         permutation |= SHADERPERMUTATION_DIFFUSE;
5689                         if (specularscale > 0)
5690                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5691                 }
5692                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5693                 {
5694                         // deluxemapping (light direction texture)
5695                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5696                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5697                         else
5698                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5699                         permutation |= SHADERPERMUTATION_DIFFUSE;
5700                         if (specularscale > 0)
5701                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5702                 }
5703                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5704                 {
5705                         // fake deluxemapping (uniform light direction in tangentspace)
5706                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5707                         permutation |= SHADERPERMUTATION_DIFFUSE;
5708                         if (specularscale > 0)
5709                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5710                 }
5711                 else if (rsurface.uselightmaptexture)
5712                 {
5713                         // ordinary lightmapping (q1bsp, q3bsp)
5714                         mode = SHADERMODE_LIGHTMAP;
5715                 }
5716                 else
5717                 {
5718                         // ordinary vertex coloring (q3bsp)
5719                         mode = SHADERMODE_VERTEXCOLOR;
5720                 }
5721                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5722                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5723                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5724         }
5725         if(!allow_colormod)
5726                 colormod = dummy_colormod;
5727         switch(vid.renderpath)
5728         {
5729         case RENDERPATH_D3D9:
5730 #ifdef SUPPORTD3D
5731                 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);
5732                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5733                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5734                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5735                 if (mode == SHADERMODE_LIGHTSOURCE)
5736                 {
5737                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5738                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5739                 }
5740                 else
5741                 {
5742                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5743                         {
5744                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5745                         }
5746                 }
5747                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5748                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5749                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5750                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5751                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5752
5753                 if (mode == SHADERMODE_LIGHTSOURCE)
5754                 {
5755                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5756                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5757                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5758                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5759                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5760
5761                         // additive passes are only darkened by fog, not tinted
5762                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5763                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5764                 }
5765                 else
5766                 {
5767                         if (mode == SHADERMODE_FLATCOLOR)
5768                         {
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5770                         }
5771                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5772                         {
5773                                 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]);
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5776                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5777                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5778                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5779                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5780                         }
5781                         else
5782                         {
5783                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5784                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5785                                 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);
5786                                 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);
5787                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5788                         }
5789                         // additive passes are only darkened by fog, not tinted
5790                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5791                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5792                         else
5793                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5794                         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);
5795                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5796                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5797                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5798                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5799                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5800                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5801                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5802                         if (mode == SHADERMODE_WATER)
5803                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5804                 }
5805                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5806                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5807                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5808                 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));
5809                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5810                 if (rsurface.texture->pantstexture)
5811                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5812                 else
5813                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5814                 if (rsurface.texture->shirttexture)
5815                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5816                 else
5817                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5818                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5819                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5820                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5821                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5822                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5823                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5824                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5825
5826                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5827                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5828                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5829                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5830                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5831                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5832                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5833                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5834                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5835                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5836                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5837                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5838                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5839                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5840                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5841                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5842                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5843                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5844                 {
5845                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5846                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5847                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5848                 }
5849                 else
5850                 {
5851                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5852                 }
5853 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5854 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5855                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5856                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5857                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5858                 {
5859                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5860                         if (rsurface.rtlight)
5861                         {
5862                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5863                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5864                         }
5865                 }
5866 #endif
5867                 break;
5868         case RENDERPATH_D3D10:
5869                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5870                 break;
5871         case RENDERPATH_D3D11:
5872                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5873                 break;
5874         case RENDERPATH_GL20:
5875                 if (!vid.useinterleavedarrays)
5876                 {
5877                         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);
5878                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5879                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5880                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5881                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5882                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5883                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5884                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5885                 }
5886                 else
5887                 {
5888                         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);
5889                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5890                 }
5891                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5892                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5893                 if (mode == SHADERMODE_LIGHTSOURCE)
5894                 {
5895                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5896                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5897                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5898                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5899                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5900                         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);
5901         
5902                         // additive passes are only darkened by fog, not tinted
5903                         if (r_glsl_permutation->loc_FogColor >= 0)
5904                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5905                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5906                 }
5907                 else
5908                 {
5909                         if (mode == SHADERMODE_FLATCOLOR)
5910                         {
5911                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5912                         }
5913                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5914                         {
5915                                 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]);
5916                                 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]);
5917                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5918                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5919                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5920                                 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]);
5921                                 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]);
5922                         }
5923                         else
5924                         {
5925                                 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]);
5926                                 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]);
5927                                 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);
5928                                 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);
5929                                 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);
5930                         }
5931                         // additive passes are only darkened by fog, not tinted
5932                         if (r_glsl_permutation->loc_FogColor >= 0)
5933                         {
5934                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5935                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5936                                 else
5937                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5938                         }
5939                         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);
5940                         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]);
5941                         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]);
5942                         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]);
5943                         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]);
5944                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5945                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5946                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5947                         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]);
5948                 }
5949                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5950                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5951                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5952                 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]);
5953                 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]);
5954
5955                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5956                 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));
5957                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5958                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5959                 {
5960                         if (rsurface.texture->pantstexture)
5961                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5962                         else
5963                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5964                 }
5965                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5966                 {
5967                         if (rsurface.texture->shirttexture)
5968                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5969                         else
5970                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5971                 }
5972                 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]);
5973                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5974                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5975                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5976                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5977                 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]);
5978                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5979
5980         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5981         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5982         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5983                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5984                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5985                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5986                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5987                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5988                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5989                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5990                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5991                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5992                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5993                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5994                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5995                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5996                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5997                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5998                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5999                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6000                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6001                 {
6002                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6003                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6004                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6005                 }
6006                 else
6007                 {
6008                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6009                 }
6010 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6011 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6012                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6013                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6014                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6015                 {
6016                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6017                         if (rsurface.rtlight)
6018                         {
6019                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6020                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6021                         }
6022                 }
6023                 CHECKGLERROR
6024                 break;
6025         case RENDERPATH_CGGL:
6026 #ifdef SUPPORTCG
6027                 if (!vid.useinterleavedarrays)
6028                 {
6029                         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);
6030                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6031                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6032                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6033                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6034                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6035                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6036                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6037                 }
6038                 else
6039                 {
6040                         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);
6041                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6042                 }
6043                 R_SetupShader_SetPermutationCG(mode, permutation);
6044                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6045                 if (mode == SHADERMODE_LIGHTSOURCE)
6046                 {
6047                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6048                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6049                 }
6050                 else
6051                 {
6052                         if (mode == SHADERMODE_LIGHTDIRECTION)
6053                         {
6054                                 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
6055                         }
6056                 }
6057                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6058                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6059                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6060                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6061                 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
6062                 CHECKGLERROR
6063
6064                 if (mode == SHADERMODE_LIGHTSOURCE)
6065                 {
6066                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6067                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6068                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6069                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6070                         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
6071
6072                         // additive passes are only darkened by fog, not tinted
6073                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6074                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6075                 }
6076                 else
6077                 {
6078                         if (mode == SHADERMODE_FLATCOLOR)
6079                         {
6080                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6081                         }
6082                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6083                         {
6084                                 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
6085                                 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
6086                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6087                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6088                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6089                                 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
6090                                 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
6091                         }
6092                         else
6093                         {
6094                                 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
6095                                 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
6096                                 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
6097                                 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
6098                                 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
6099                         }
6100                         // additive passes are only darkened by fog, not tinted
6101                         if (r_cg_permutation->fp_FogColor)
6102                         {
6103                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6104                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6105                                 else
6106                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6107                                 CHECKCGERROR
6108                         }
6109                         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
6110                         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
6111                         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
6112                         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
6113                         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
6114                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6115                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6116                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6117                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6118                 }
6119                 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
6120                 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
6121                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6122                 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
6123                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6124                 if (r_cg_permutation->fp_Color_Pants)
6125                 {
6126                         if (rsurface.texture->pantstexture)
6127                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6128                         else
6129                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6130                         CHECKCGERROR
6131                 }
6132                 if (r_cg_permutation->fp_Color_Shirt)
6133                 {
6134                         if (rsurface.texture->shirttexture)
6135                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6136                         else
6137                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6138                         CHECKCGERROR
6139                 }
6140                 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
6141                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6142                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6143                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6144                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6145                 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
6146                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6147
6148         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6149         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6150         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6152                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6153                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6158                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6159                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6161                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6162                 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
6163                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6164                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6165                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6166                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6167                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6168                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6169                 {
6170                         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
6171                         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
6172                         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
6173                 }
6174                 else
6175                 {
6176                         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
6177                 }
6178                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6179                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6180                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6181                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6182                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6183                 {
6184                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6185                         if (rsurface.rtlight)
6186                         {
6187                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6188                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6189                         }
6190                 }
6191
6192                 CHECKGLERROR
6193 #endif
6194                 break;
6195         case RENDERPATH_GL13:
6196         case RENDERPATH_GL11:
6197                 break;
6198         }
6199 }
6200
6201 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6202 {
6203         // select a permutation of the lighting shader appropriate to this
6204         // combination of texture, entity, light source, and fogging, only use the
6205         // minimum features necessary to avoid wasting rendering time in the
6206         // fragment shader on features that are not being used
6207         unsigned int permutation = 0;
6208         unsigned int mode = 0;
6209         const float *lightcolorbase = rtlight->currentcolor;
6210         float ambientscale = rtlight->ambientscale;
6211         float diffusescale = rtlight->diffusescale;
6212         float specularscale = rtlight->specularscale;
6213         // this is the location of the light in view space
6214         vec3_t viewlightorigin;
6215         // this transforms from view space (camera) to light space (cubemap)
6216         matrix4x4_t viewtolight;
6217         matrix4x4_t lighttoview;
6218         float viewtolight16f[16];
6219         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6220         // light source
6221         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6222         if (rtlight->currentcubemap != r_texture_whitecube)
6223                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6224         if (diffusescale > 0)
6225                 permutation |= SHADERPERMUTATION_DIFFUSE;
6226         if (specularscale > 0)
6227                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6228         if (r_shadow_usingshadowmap2d)
6229         {
6230                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6231                 if (r_shadow_shadowmapvsdct)
6232                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6233
6234                 if (r_shadow_shadowmapsampler)
6235                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6236                 if (r_shadow_shadowmappcf > 1)
6237                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6238                 else if (r_shadow_shadowmappcf)
6239                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6240         }
6241         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6242         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6243         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6244         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6245         switch(vid.renderpath)
6246         {
6247         case RENDERPATH_D3D9:
6248 #ifdef SUPPORTD3D
6249                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6250                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6251                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6252                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6253                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6254                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6255                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6256                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6257                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6258                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6259                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6260
6261                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6262                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6263                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6264                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6265                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6266                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6267 #endif
6268                 break;
6269         case RENDERPATH_D3D10:
6270                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6271                 break;
6272         case RENDERPATH_D3D11:
6273                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6274                 break;
6275         case RENDERPATH_GL20:
6276                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6277                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6278                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6279                 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);
6280                 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);
6281                 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);
6282                 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]);
6283                 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]);
6284                 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));
6285                 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]);
6286                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6287
6288                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6289                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6290                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6291                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6292                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6293                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6294                 break;
6295         case RENDERPATH_CGGL:
6296 #ifdef SUPPORTCG
6297                 R_SetupShader_SetPermutationCG(mode, permutation);
6298                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6299                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6300                 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
6301                 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
6302                 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
6303                 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
6304                 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
6305                 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
6306                 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
6307                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6308
6309                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6310                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6311                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6312                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6313                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6314                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6315 #endif
6316                 break;
6317         case RENDERPATH_GL13:
6318         case RENDERPATH_GL11:
6319                 break;
6320         }
6321 }
6322
6323 #define SKINFRAME_HASH 1024
6324
6325 typedef struct
6326 {
6327         int loadsequence; // incremented each level change
6328         memexpandablearray_t array;
6329         skinframe_t *hash[SKINFRAME_HASH];
6330 }
6331 r_skinframe_t;
6332 r_skinframe_t r_skinframe;
6333
6334 void R_SkinFrame_PrepareForPurge(void)
6335 {
6336         r_skinframe.loadsequence++;
6337         // wrap it without hitting zero
6338         if (r_skinframe.loadsequence >= 200)
6339                 r_skinframe.loadsequence = 1;
6340 }
6341
6342 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6343 {
6344         if (!skinframe)
6345                 return;
6346         // mark the skinframe as used for the purging code
6347         skinframe->loadsequence = r_skinframe.loadsequence;
6348 }
6349
6350 void R_SkinFrame_Purge(void)
6351 {
6352         int i;
6353         skinframe_t *s;
6354         for (i = 0;i < SKINFRAME_HASH;i++)
6355         {
6356                 for (s = r_skinframe.hash[i];s;s = s->next)
6357                 {
6358                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6359                         {
6360                                 if (s->merged == s->base)
6361                                         s->merged = NULL;
6362                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6363                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6364                                 R_PurgeTexture(s->merged);s->merged = NULL;
6365                                 R_PurgeTexture(s->base  );s->base   = NULL;
6366                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6367                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6368                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6369                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6370                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6371                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6372                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6373                                 s->loadsequence = 0;
6374                         }
6375                 }
6376         }
6377 }
6378
6379 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6380         skinframe_t *item;
6381         char basename[MAX_QPATH];
6382
6383         Image_StripImageExtension(name, basename, sizeof(basename));
6384
6385         if( last == NULL ) {
6386                 int hashindex;
6387                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6388                 item = r_skinframe.hash[hashindex];
6389         } else {
6390                 item = last->next;
6391         }
6392
6393         // linearly search through the hash bucket
6394         for( ; item ; item = item->next ) {
6395                 if( !strcmp( item->basename, basename ) ) {
6396                         return item;
6397                 }
6398         }
6399         return NULL;
6400 }
6401
6402 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6403 {
6404         skinframe_t *item;
6405         int hashindex;
6406         char basename[MAX_QPATH];
6407
6408         Image_StripImageExtension(name, basename, sizeof(basename));
6409
6410         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6411         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6412                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6413                         break;
6414
6415         if (!item) {
6416                 rtexture_t *dyntexture;
6417                 // check whether its a dynamic texture
6418                 dyntexture = CL_GetDynTexture( basename );
6419                 if (!add && !dyntexture)
6420                         return NULL;
6421                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6422                 memset(item, 0, sizeof(*item));
6423                 strlcpy(item->basename, basename, sizeof(item->basename));
6424                 item->base = dyntexture; // either NULL or dyntexture handle
6425                 item->textureflags = textureflags;
6426                 item->comparewidth = comparewidth;
6427                 item->compareheight = compareheight;
6428                 item->comparecrc = comparecrc;
6429                 item->next = r_skinframe.hash[hashindex];
6430                 r_skinframe.hash[hashindex] = item;
6431         }
6432         else if( item->base == NULL )
6433         {
6434                 rtexture_t *dyntexture;
6435                 // check whether its a dynamic texture
6436                 // 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]
6437                 dyntexture = CL_GetDynTexture( basename );
6438                 item->base = dyntexture; // either NULL or dyntexture handle
6439         }
6440
6441         R_SkinFrame_MarkUsed(item);
6442         return item;
6443 }
6444
6445 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6446         { \
6447                 unsigned long long avgcolor[5], wsum; \
6448                 int pix, comp, w; \
6449                 avgcolor[0] = 0; \
6450                 avgcolor[1] = 0; \
6451                 avgcolor[2] = 0; \
6452                 avgcolor[3] = 0; \
6453                 avgcolor[4] = 0; \
6454                 wsum = 0; \
6455                 for(pix = 0; pix < cnt; ++pix) \
6456                 { \
6457                         w = 0; \
6458                         for(comp = 0; comp < 3; ++comp) \
6459                                 w += getpixel; \
6460                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6461                         { \
6462                                 ++wsum; \
6463                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6464                                 w = getpixel; \
6465                                 for(comp = 0; comp < 3; ++comp) \
6466                                         avgcolor[comp] += getpixel * w; \
6467                                 avgcolor[3] += w; \
6468                         } \
6469                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6470                         avgcolor[4] += getpixel; \
6471                 } \
6472                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6473                         avgcolor[3] = 1; \
6474                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6475                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6476                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6477                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6478         }
6479
6480 extern cvar_t gl_picmip;
6481 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6482 {
6483         int j;
6484         unsigned char *pixels;
6485         unsigned char *bumppixels;
6486         unsigned char *basepixels = NULL;
6487         int basepixels_width = 0;
6488         int basepixels_height = 0;
6489         skinframe_t *skinframe;
6490         rtexture_t *ddsbase = NULL;
6491         qboolean ddshasalpha = false;
6492         float ddsavgcolor[4];
6493         char basename[MAX_QPATH];
6494         int miplevel = R_PicmipForFlags(textureflags);
6495         int savemiplevel = miplevel;
6496         int mymiplevel;
6497
6498         if (cls.state == ca_dedicated)
6499                 return NULL;
6500
6501         // return an existing skinframe if already loaded
6502         // if loading of the first image fails, don't make a new skinframe as it
6503         // would cause all future lookups of this to be missing
6504         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6505         if (skinframe && skinframe->base)
6506                 return skinframe;
6507
6508         Image_StripImageExtension(name, basename, sizeof(basename));
6509
6510         // check for DDS texture file first
6511         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6512         {
6513                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6514                 if (basepixels == NULL)
6515                         return NULL;
6516         }
6517
6518         // FIXME handle miplevel
6519
6520         if (developer_loading.integer)
6521                 Con_Printf("loading skin \"%s\"\n", name);
6522
6523         // we've got some pixels to store, so really allocate this new texture now
6524         if (!skinframe)
6525                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6526         skinframe->stain = NULL;
6527         skinframe->merged = NULL;
6528         skinframe->base = NULL;
6529         skinframe->pants = NULL;
6530         skinframe->shirt = NULL;
6531         skinframe->nmap = NULL;
6532         skinframe->gloss = NULL;
6533         skinframe->glow = NULL;
6534         skinframe->fog = NULL;
6535         skinframe->reflect = NULL;
6536         skinframe->hasalpha = false;
6537
6538         if (ddsbase)
6539         {
6540                 skinframe->base = ddsbase;
6541                 skinframe->hasalpha = ddshasalpha;
6542                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6543                 if (r_loadfog && skinframe->hasalpha)
6544                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6545                 //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]);
6546         }
6547         else
6548         {
6549                 basepixels_width = image_width;
6550                 basepixels_height = image_height;
6551                 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);
6552                 if (textureflags & TEXF_ALPHA)
6553                 {
6554                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6555                         {
6556                                 if (basepixels[j] < 255)
6557                                 {
6558                                         skinframe->hasalpha = true;
6559                                         break;
6560                                 }
6561                         }
6562                         if (r_loadfog && skinframe->hasalpha)
6563                         {
6564                                 // has transparent pixels
6565                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6566                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6567                                 {
6568                                         pixels[j+0] = 255;
6569                                         pixels[j+1] = 255;
6570                                         pixels[j+2] = 255;
6571                                         pixels[j+3] = basepixels[j+3];
6572                                 }
6573                                 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);
6574                                 Mem_Free(pixels);
6575                         }
6576                 }
6577                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6578                 //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]);
6579                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6580                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6581                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6582                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6583         }
6584
6585         if (r_loaddds)
6586         {
6587                 mymiplevel = savemiplevel;
6588                 if (r_loadnormalmap)
6589                         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);
6590                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6591                 if (r_loadgloss)
6592                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6593                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6594                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6595                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6596         }
6597
6598         // _norm is the name used by tenebrae and has been adopted as standard
6599         if (r_loadnormalmap && skinframe->nmap == NULL)
6600         {
6601                 mymiplevel = savemiplevel;
6602                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6603                 {
6604                         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);
6605                         Mem_Free(pixels);
6606                         pixels = NULL;
6607                 }
6608                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6609                 {
6610                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6611                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6612                         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);
6613                         Mem_Free(pixels);
6614                         Mem_Free(bumppixels);
6615                 }
6616                 else if (r_shadow_bumpscale_basetexture.value > 0)
6617                 {
6618                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6619                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6620                         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);
6621                         Mem_Free(pixels);
6622                 }
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6624                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6625         }
6626
6627         // _luma is supported only for tenebrae compatibility
6628         // _glow is the preferred name
6629         mymiplevel = savemiplevel;
6630         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))))
6631         {
6632                 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);
6633                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6634                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6635                 Mem_Free(pixels);pixels = NULL;
6636         }
6637
6638         mymiplevel = savemiplevel;
6639         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6640         {
6641                 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);
6642                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6643                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6644                 Mem_Free(pixels);
6645                 pixels = NULL;
6646         }
6647
6648         mymiplevel = savemiplevel;
6649         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6650         {
6651                 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);
6652                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6653                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6654                 Mem_Free(pixels);
6655                 pixels = NULL;
6656         }
6657
6658         mymiplevel = savemiplevel;
6659         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6660         {
6661                 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);
6662                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6663                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6664                 Mem_Free(pixels);
6665                 pixels = NULL;
6666         }
6667
6668         mymiplevel = savemiplevel;
6669         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6670         {
6671                 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);
6672                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6673                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6674                 Mem_Free(pixels);
6675                 pixels = NULL;
6676         }
6677
6678         if (basepixels)
6679                 Mem_Free(basepixels);
6680
6681         return skinframe;
6682 }
6683
6684 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6685 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6686 {
6687         int i;
6688         unsigned char *temp1, *temp2;
6689         skinframe_t *skinframe;
6690
6691         if (cls.state == ca_dedicated)
6692                 return NULL;
6693
6694         // if already loaded just return it, otherwise make a new skinframe
6695         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6696         if (skinframe && skinframe->base)
6697                 return skinframe;
6698
6699         skinframe->stain = NULL;
6700         skinframe->merged = NULL;
6701         skinframe->base = NULL;
6702         skinframe->pants = NULL;
6703         skinframe->shirt = NULL;
6704         skinframe->nmap = NULL;
6705         skinframe->gloss = NULL;
6706         skinframe->glow = NULL;
6707         skinframe->fog = NULL;
6708         skinframe->reflect = NULL;
6709         skinframe->hasalpha = false;
6710
6711         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6712         if (!skindata)
6713                 return NULL;
6714
6715         if (developer_loading.integer)
6716                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6717
6718         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6719         {
6720                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6721                 temp2 = temp1 + width * height * 4;
6722                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6723                 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);
6724                 Mem_Free(temp1);
6725         }
6726         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6727         if (textureflags & TEXF_ALPHA)
6728         {
6729                 for (i = 3;i < width * height * 4;i += 4)
6730                 {
6731                         if (skindata[i] < 255)
6732                         {
6733                                 skinframe->hasalpha = true;
6734                                 break;
6735                         }
6736                 }
6737                 if (r_loadfog && skinframe->hasalpha)
6738                 {
6739                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6740                         memcpy(fogpixels, skindata, width * height * 4);
6741                         for (i = 0;i < width * height * 4;i += 4)
6742                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6743                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6744                         Mem_Free(fogpixels);
6745                 }
6746         }
6747
6748         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6749         //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]);
6750
6751         return skinframe;
6752 }
6753
6754 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6755 {
6756         int i;
6757         int featuresmask;
6758         skinframe_t *skinframe;
6759
6760         if (cls.state == ca_dedicated)
6761                 return NULL;
6762
6763         // if already loaded just return it, otherwise make a new skinframe
6764         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6765         if (skinframe && skinframe->base)
6766                 return skinframe;
6767
6768         skinframe->stain = NULL;
6769         skinframe->merged = NULL;
6770         skinframe->base = NULL;
6771         skinframe->pants = NULL;
6772         skinframe->shirt = NULL;
6773         skinframe->nmap = NULL;
6774         skinframe->gloss = NULL;
6775         skinframe->glow = NULL;
6776         skinframe->fog = NULL;
6777         skinframe->reflect = NULL;
6778         skinframe->hasalpha = false;
6779
6780         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6781         if (!skindata)
6782                 return NULL;
6783
6784         if (developer_loading.integer)
6785                 Con_Printf("loading quake skin \"%s\"\n", name);
6786
6787         // 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)
6788         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6789         memcpy(skinframe->qpixels, skindata, width*height);
6790         skinframe->qwidth = width;
6791         skinframe->qheight = height;
6792
6793         featuresmask = 0;
6794         for (i = 0;i < width * height;i++)
6795                 featuresmask |= palette_featureflags[skindata[i]];
6796
6797         skinframe->hasalpha = false;
6798         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6799         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6800         skinframe->qgeneratemerged = true;
6801         skinframe->qgeneratebase = skinframe->qhascolormapping;
6802         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6803
6804         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6805         //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]);
6806
6807         return skinframe;
6808 }
6809
6810 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6811 {
6812         int width;
6813         int height;
6814         unsigned char *skindata;
6815
6816         if (!skinframe->qpixels)
6817                 return;
6818
6819         if (!skinframe->qhascolormapping)
6820                 colormapped = false;
6821
6822         if (colormapped)
6823         {
6824                 if (!skinframe->qgeneratebase)
6825                         return;
6826         }
6827         else
6828         {
6829                 if (!skinframe->qgeneratemerged)
6830                         return;
6831         }
6832
6833         width = skinframe->qwidth;
6834         height = skinframe->qheight;
6835         skindata = skinframe->qpixels;
6836
6837         if (skinframe->qgeneratenmap)
6838         {
6839                 unsigned char *temp1, *temp2;
6840                 skinframe->qgeneratenmap = false;
6841                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6842                 temp2 = temp1 + width * height * 4;
6843                 // use either a custom palette or the quake palette
6844                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6845                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6846                 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);
6847                 Mem_Free(temp1);
6848         }
6849
6850         if (skinframe->qgenerateglow)
6851         {
6852                 skinframe->qgenerateglow = false;
6853                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6854         }
6855
6856         if (colormapped)
6857         {
6858                 skinframe->qgeneratebase = false;
6859                 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);
6860                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6861                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6862         }
6863         else
6864         {
6865                 skinframe->qgeneratemerged = false;
6866                 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);
6867         }
6868
6869         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6870         {
6871                 Mem_Free(skinframe->qpixels);
6872                 skinframe->qpixels = NULL;
6873         }
6874 }
6875
6876 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)
6877 {
6878         int i;
6879         skinframe_t *skinframe;
6880
6881         if (cls.state == ca_dedicated)
6882                 return NULL;
6883
6884         // if already loaded just return it, otherwise make a new skinframe
6885         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6886         if (skinframe && skinframe->base)
6887                 return skinframe;
6888
6889         skinframe->stain = NULL;
6890         skinframe->merged = NULL;
6891         skinframe->base = NULL;
6892         skinframe->pants = NULL;
6893         skinframe->shirt = NULL;
6894         skinframe->nmap = NULL;
6895         skinframe->gloss = NULL;
6896         skinframe->glow = NULL;
6897         skinframe->fog = NULL;
6898         skinframe->reflect = NULL;
6899         skinframe->hasalpha = false;
6900
6901         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6902         if (!skindata)
6903                 return NULL;
6904
6905         if (developer_loading.integer)
6906                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6907
6908         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6909         if (textureflags & TEXF_ALPHA)
6910         {
6911                 for (i = 0;i < width * height;i++)
6912                 {
6913                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6914                         {
6915                                 skinframe->hasalpha = true;
6916                                 break;
6917                         }
6918                 }
6919                 if (r_loadfog && skinframe->hasalpha)
6920                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6921         }
6922
6923         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6924         //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]);
6925
6926         return skinframe;
6927 }
6928
6929 skinframe_t *R_SkinFrame_LoadMissing(void)
6930 {
6931         skinframe_t *skinframe;
6932
6933         if (cls.state == ca_dedicated)
6934                 return NULL;
6935
6936         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6937         skinframe->stain = NULL;
6938         skinframe->merged = NULL;
6939         skinframe->base = NULL;
6940         skinframe->pants = NULL;
6941         skinframe->shirt = NULL;
6942         skinframe->nmap = NULL;
6943         skinframe->gloss = NULL;
6944         skinframe->glow = NULL;
6945         skinframe->fog = NULL;
6946         skinframe->reflect = NULL;
6947         skinframe->hasalpha = false;
6948
6949         skinframe->avgcolor[0] = rand() / RAND_MAX;
6950         skinframe->avgcolor[1] = rand() / RAND_MAX;
6951         skinframe->avgcolor[2] = rand() / RAND_MAX;
6952         skinframe->avgcolor[3] = 1;
6953
6954         return skinframe;
6955 }
6956
6957 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6958 typedef struct suffixinfo_s
6959 {
6960         const char *suffix;
6961         qboolean flipx, flipy, flipdiagonal;
6962 }
6963 suffixinfo_t;
6964 static suffixinfo_t suffix[3][6] =
6965 {
6966         {
6967                 {"px",   false, false, false},
6968                 {"nx",   false, false, false},
6969                 {"py",   false, false, false},
6970                 {"ny",   false, false, false},
6971                 {"pz",   false, false, false},
6972                 {"nz",   false, false, false}
6973         },
6974         {
6975                 {"posx", false, false, false},
6976                 {"negx", false, false, false},
6977                 {"posy", false, false, false},
6978                 {"negy", false, false, false},
6979                 {"posz", false, false, false},
6980                 {"negz", false, false, false}
6981         },
6982         {
6983                 {"rt",    true, false,  true},
6984                 {"lf",   false,  true,  true},
6985                 {"ft",    true,  true, false},
6986                 {"bk",   false, false, false},
6987                 {"up",    true, false,  true},
6988                 {"dn",    true, false,  true}
6989         }
6990 };
6991
6992 static int componentorder[4] = {0, 1, 2, 3};
6993
6994 rtexture_t *R_LoadCubemap(const char *basename)
6995 {
6996         int i, j, cubemapsize;
6997         unsigned char *cubemappixels, *image_buffer;
6998         rtexture_t *cubemaptexture;
6999         char name[256];
7000         // must start 0 so the first loadimagepixels has no requested width/height
7001         cubemapsize = 0;
7002         cubemappixels = NULL;
7003         cubemaptexture = NULL;
7004         // keep trying different suffix groups (posx, px, rt) until one loads
7005         for (j = 0;j < 3 && !cubemappixels;j++)
7006         {
7007                 // load the 6 images in the suffix group
7008                 for (i = 0;i < 6;i++)
7009                 {
7010                         // generate an image name based on the base and and suffix
7011                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7012                         // load it
7013                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7014                         {
7015                                 // an image loaded, make sure width and height are equal
7016                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7017                                 {
7018                                         // if this is the first image to load successfully, allocate the cubemap memory
7019                                         if (!cubemappixels && image_width >= 1)
7020                                         {
7021                                                 cubemapsize = image_width;
7022                                                 // note this clears to black, so unavailable sides are black
7023                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7024                                         }
7025                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7026                                         if (cubemappixels)
7027                                                 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);
7028                                 }
7029                                 else
7030                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7031                                 // free the image
7032                                 Mem_Free(image_buffer);
7033                         }
7034                 }
7035         }
7036         // if a cubemap loaded, upload it
7037         if (cubemappixels)
7038         {
7039                 if (developer_loading.integer)
7040                         Con_Printf("loading cubemap \"%s\"\n", basename);
7041
7042                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7043                 Mem_Free(cubemappixels);
7044         }
7045         else
7046         {
7047                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7048                 if (developer_loading.integer)
7049                 {
7050                         Con_Printf("(tried tried images ");
7051                         for (j = 0;j < 3;j++)
7052                                 for (i = 0;i < 6;i++)
7053                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7054                         Con_Print(" and was unable to find any of them).\n");
7055                 }
7056         }
7057         return cubemaptexture;
7058 }
7059
7060 rtexture_t *R_GetCubemap(const char *basename)
7061 {
7062         int i;
7063         for (i = 0;i < r_texture_numcubemaps;i++)
7064                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7065                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7066         if (i >= MAX_CUBEMAPS)
7067                 return r_texture_whitecube;
7068         r_texture_numcubemaps++;
7069         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7070         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7071         return r_texture_cubemaps[i].texture;
7072 }
7073
7074 void R_FreeCubemaps(void)
7075 {
7076         int i;
7077         for (i = 0;i < r_texture_numcubemaps;i++)
7078         {
7079                 if (developer_loading.integer)
7080                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7081                 if (r_texture_cubemaps[i].texture)
7082                         R_FreeTexture(r_texture_cubemaps[i].texture);
7083         }
7084         r_texture_numcubemaps = 0;
7085 }
7086
7087 void R_Main_FreeViewCache(void)
7088 {
7089         if (r_refdef.viewcache.entityvisible)
7090                 Mem_Free(r_refdef.viewcache.entityvisible);
7091         if (r_refdef.viewcache.world_pvsbits)
7092                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7093         if (r_refdef.viewcache.world_leafvisible)
7094                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7095         if (r_refdef.viewcache.world_surfacevisible)
7096                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7097         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7098 }
7099
7100 void R_Main_ResizeViewCache(void)
7101 {
7102         int numentities = r_refdef.scene.numentities;
7103         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7104         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7105         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7106         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7107         if (r_refdef.viewcache.maxentities < numentities)
7108         {
7109                 r_refdef.viewcache.maxentities = numentities;
7110                 if (r_refdef.viewcache.entityvisible)
7111                         Mem_Free(r_refdef.viewcache.entityvisible);
7112                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7113         }
7114         if (r_refdef.viewcache.world_numclusters != numclusters)
7115         {
7116                 r_refdef.viewcache.world_numclusters = numclusters;
7117                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7118                 if (r_refdef.viewcache.world_pvsbits)
7119                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7120                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7121         }
7122         if (r_refdef.viewcache.world_numleafs != numleafs)
7123         {
7124                 r_refdef.viewcache.world_numleafs = numleafs;
7125                 if (r_refdef.viewcache.world_leafvisible)
7126                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7127                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7128         }
7129         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7130         {
7131                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7132                 if (r_refdef.viewcache.world_surfacevisible)
7133                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7134                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7135         }
7136 }
7137
7138 extern rtexture_t *loadingscreentexture;
7139 void gl_main_start(void)
7140 {
7141         loadingscreentexture = NULL;
7142         r_texture_blanknormalmap = NULL;
7143         r_texture_white = NULL;
7144         r_texture_grey128 = NULL;
7145         r_texture_black = NULL;
7146         r_texture_whitecube = NULL;
7147         r_texture_normalizationcube = NULL;
7148         r_texture_fogattenuation = NULL;
7149         r_texture_fogheighttexture = NULL;
7150         r_texture_gammaramps = NULL;
7151         r_texture_numcubemaps = 0;
7152
7153         r_loaddds = r_texture_dds_load.integer;
7154         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7155
7156         switch(vid.renderpath)
7157         {
7158         case RENDERPATH_GL20:
7159         case RENDERPATH_CGGL:
7160         case RENDERPATH_D3D9:
7161         case RENDERPATH_D3D10:
7162         case RENDERPATH_D3D11:
7163                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7164                 Cvar_SetValueQuick(&gl_combine, 1);
7165                 Cvar_SetValueQuick(&r_glsl, 1);
7166                 r_loadnormalmap = true;
7167                 r_loadgloss = true;
7168                 r_loadfog = false;
7169                 break;
7170         case RENDERPATH_GL13:
7171                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7172                 Cvar_SetValueQuick(&gl_combine, 1);
7173                 Cvar_SetValueQuick(&r_glsl, 0);
7174                 r_loadnormalmap = false;
7175                 r_loadgloss = false;
7176                 r_loadfog = true;
7177                 break;
7178         case RENDERPATH_GL11:
7179                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7180                 Cvar_SetValueQuick(&gl_combine, 0);
7181                 Cvar_SetValueQuick(&r_glsl, 0);
7182                 r_loadnormalmap = false;
7183                 r_loadgloss = false;
7184                 r_loadfog = true;
7185                 break;
7186         }
7187
7188         R_AnimCache_Free();
7189         R_FrameData_Reset();
7190
7191         r_numqueries = 0;
7192         r_maxqueries = 0;
7193         memset(r_queries, 0, sizeof(r_queries));
7194
7195         r_qwskincache = NULL;
7196         r_qwskincache_size = 0;
7197
7198         // set up r_skinframe loading system for textures
7199         memset(&r_skinframe, 0, sizeof(r_skinframe));
7200         r_skinframe.loadsequence = 1;
7201         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7202
7203         r_main_texturepool = R_AllocTexturePool();
7204         R_BuildBlankTextures();
7205         R_BuildNoTexture();
7206         if (vid.support.arb_texture_cube_map)
7207         {
7208                 R_BuildWhiteCube();
7209                 R_BuildNormalizationCube();
7210         }
7211         r_texture_fogattenuation = NULL;
7212         r_texture_fogheighttexture = NULL;
7213         r_texture_gammaramps = NULL;
7214         //r_texture_fogintensity = NULL;
7215         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7216         memset(&r_waterstate, 0, sizeof(r_waterstate));
7217         r_glsl_permutation = NULL;
7218         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7219         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7220         glslshaderstring = NULL;
7221 #ifdef SUPPORTCG
7222         r_cg_permutation = NULL;
7223         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7224         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7225         cgshaderstring = NULL;
7226 #endif
7227 #ifdef SUPPORTD3D
7228         r_hlsl_permutation = NULL;
7229         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7230         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7231         hlslshaderstring = NULL;
7232 #endif
7233         memset(&r_svbsp, 0, sizeof (r_svbsp));
7234
7235         r_refdef.fogmasktable_density = 0;
7236 }
7237
7238 void gl_main_shutdown(void)
7239 {
7240         R_AnimCache_Free();
7241         R_FrameData_Reset();
7242
7243         R_Main_FreeViewCache();
7244
7245         switch(vid.renderpath)
7246         {
7247         case RENDERPATH_GL11:
7248         case RENDERPATH_GL13:
7249         case RENDERPATH_GL20:
7250         case RENDERPATH_CGGL:
7251                 if (r_maxqueries)
7252                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7253                 break;
7254         case RENDERPATH_D3D9:
7255                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7256                 break;
7257         case RENDERPATH_D3D10:
7258                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7259                 break;
7260         case RENDERPATH_D3D11:
7261                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7262                 break;
7263         }
7264
7265         r_numqueries = 0;
7266         r_maxqueries = 0;
7267         memset(r_queries, 0, sizeof(r_queries));
7268
7269         r_qwskincache = NULL;
7270         r_qwskincache_size = 0;
7271
7272         // clear out the r_skinframe state
7273         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7274         memset(&r_skinframe, 0, sizeof(r_skinframe));
7275
7276         if (r_svbsp.nodes)
7277                 Mem_Free(r_svbsp.nodes);
7278         memset(&r_svbsp, 0, sizeof (r_svbsp));
7279         R_FreeTexturePool(&r_main_texturepool);
7280         loadingscreentexture = NULL;
7281         r_texture_blanknormalmap = NULL;
7282         r_texture_white = NULL;
7283         r_texture_grey128 = NULL;
7284         r_texture_black = NULL;
7285         r_texture_whitecube = NULL;
7286         r_texture_normalizationcube = NULL;
7287         r_texture_fogattenuation = NULL;
7288         r_texture_fogheighttexture = NULL;
7289         r_texture_gammaramps = NULL;
7290         r_texture_numcubemaps = 0;
7291         //r_texture_fogintensity = NULL;
7292         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7293         memset(&r_waterstate, 0, sizeof(r_waterstate));
7294         R_GLSL_Restart_f();
7295
7296         r_glsl_permutation = NULL;
7297         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7298         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7299         glslshaderstring = NULL;
7300 #ifdef SUPPORTCG
7301         r_cg_permutation = NULL;
7302         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7303         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7304         cgshaderstring = NULL;
7305 #endif
7306 #ifdef SUPPORTD3D
7307         r_hlsl_permutation = NULL;
7308         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7309         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7310         hlslshaderstring = NULL;
7311 #endif
7312 }
7313
7314 extern void CL_ParseEntityLump(char *entitystring);
7315 void gl_main_newmap(void)
7316 {
7317         // FIXME: move this code to client
7318         char *entities, entname[MAX_QPATH];
7319         if (r_qwskincache)
7320                 Mem_Free(r_qwskincache);
7321         r_qwskincache = NULL;
7322         r_qwskincache_size = 0;
7323         if (cl.worldmodel)
7324         {
7325                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7326                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7327                 {
7328                         CL_ParseEntityLump(entities);
7329                         Mem_Free(entities);
7330                         return;
7331                 }
7332                 if (cl.worldmodel->brush.entities)
7333                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7334         }
7335         R_Main_FreeViewCache();
7336
7337         R_FrameData_Reset();
7338 }
7339
7340 void GL_Main_Init(void)
7341 {
7342         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7343
7344         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7345         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7346         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7347         if (gamemode == GAME_NEHAHRA)
7348         {
7349                 Cvar_RegisterVariable (&gl_fogenable);
7350                 Cvar_RegisterVariable (&gl_fogdensity);
7351                 Cvar_RegisterVariable (&gl_fogred);
7352                 Cvar_RegisterVariable (&gl_foggreen);
7353                 Cvar_RegisterVariable (&gl_fogblue);
7354                 Cvar_RegisterVariable (&gl_fogstart);
7355                 Cvar_RegisterVariable (&gl_fogend);
7356                 Cvar_RegisterVariable (&gl_skyclip);
7357         }
7358         Cvar_RegisterVariable(&r_motionblur);
7359         Cvar_RegisterVariable(&r_motionblur_maxblur);
7360         Cvar_RegisterVariable(&r_motionblur_bmin);
7361         Cvar_RegisterVariable(&r_motionblur_vmin);
7362         Cvar_RegisterVariable(&r_motionblur_vmax);
7363         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7364         Cvar_RegisterVariable(&r_motionblur_randomize);
7365         Cvar_RegisterVariable(&r_damageblur);
7366         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7367         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7368         Cvar_RegisterVariable(&r_equalize_entities_by);
7369         Cvar_RegisterVariable(&r_equalize_entities_to);
7370         Cvar_RegisterVariable(&r_depthfirst);
7371         Cvar_RegisterVariable(&r_useinfinitefarclip);
7372         Cvar_RegisterVariable(&r_farclip_base);
7373         Cvar_RegisterVariable(&r_farclip_world);
7374         Cvar_RegisterVariable(&r_nearclip);
7375         Cvar_RegisterVariable(&r_showbboxes);
7376         Cvar_RegisterVariable(&r_showsurfaces);
7377         Cvar_RegisterVariable(&r_showtris);
7378         Cvar_RegisterVariable(&r_shownormals);
7379         Cvar_RegisterVariable(&r_showlighting);
7380         Cvar_RegisterVariable(&r_showshadowvolumes);
7381         Cvar_RegisterVariable(&r_showcollisionbrushes);
7382         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7383         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7384         Cvar_RegisterVariable(&r_showdisabledepthtest);
7385         Cvar_RegisterVariable(&r_drawportals);
7386         Cvar_RegisterVariable(&r_drawentities);
7387         Cvar_RegisterVariable(&r_draw2d);
7388         Cvar_RegisterVariable(&r_drawworld);
7389         Cvar_RegisterVariable(&r_cullentities_trace);
7390         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7391         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7392         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7393         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7394         Cvar_RegisterVariable(&r_drawviewmodel);
7395         Cvar_RegisterVariable(&r_drawexteriormodel);
7396         Cvar_RegisterVariable(&r_speeds);
7397         Cvar_RegisterVariable(&r_fullbrights);
7398         Cvar_RegisterVariable(&r_wateralpha);
7399         Cvar_RegisterVariable(&r_dynamic);
7400         Cvar_RegisterVariable(&r_fakelight);
7401         Cvar_RegisterVariable(&r_fakelight_intensity);
7402         Cvar_RegisterVariable(&r_fullbright);
7403         Cvar_RegisterVariable(&r_shadows);
7404         Cvar_RegisterVariable(&r_shadows_darken);
7405         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7406         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7407         Cvar_RegisterVariable(&r_shadows_throwdistance);
7408         Cvar_RegisterVariable(&r_shadows_throwdirection);
7409         Cvar_RegisterVariable(&r_shadows_focus);
7410         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7411         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7412         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7413         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7414         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7415         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7416         Cvar_RegisterVariable(&r_fog_exp2);
7417         Cvar_RegisterVariable(&r_drawfog);
7418         Cvar_RegisterVariable(&r_transparentdepthmasking);
7419         Cvar_RegisterVariable(&r_texture_dds_load);
7420         Cvar_RegisterVariable(&r_texture_dds_save);
7421         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7422         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7423         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7424         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7425         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7426         Cvar_RegisterVariable(&r_textureunits);
7427         Cvar_RegisterVariable(&gl_combine);
7428         Cvar_RegisterVariable(&r_glsl);
7429         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7430         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7431         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7432         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7433         Cvar_RegisterVariable(&r_glsl_postprocess);
7434         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7435         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7436         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7437         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7438         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7439         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7440         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7441         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7442
7443         Cvar_RegisterVariable(&r_water);
7444         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7445         Cvar_RegisterVariable(&r_water_clippingplanebias);
7446         Cvar_RegisterVariable(&r_water_refractdistort);
7447         Cvar_RegisterVariable(&r_water_reflectdistort);
7448         Cvar_RegisterVariable(&r_water_scissormode);
7449         Cvar_RegisterVariable(&r_lerpsprites);
7450         Cvar_RegisterVariable(&r_lerpmodels);
7451         Cvar_RegisterVariable(&r_lerplightstyles);
7452         Cvar_RegisterVariable(&r_waterscroll);
7453         Cvar_RegisterVariable(&r_bloom);
7454         Cvar_RegisterVariable(&r_bloom_colorscale);
7455         Cvar_RegisterVariable(&r_bloom_brighten);
7456         Cvar_RegisterVariable(&r_bloom_blur);
7457         Cvar_RegisterVariable(&r_bloom_resolution);
7458         Cvar_RegisterVariable(&r_bloom_colorexponent);
7459         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7460         Cvar_RegisterVariable(&r_hdr);
7461         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7462         Cvar_RegisterVariable(&r_hdr_glowintensity);
7463         Cvar_RegisterVariable(&r_hdr_range);
7464         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7465         Cvar_RegisterVariable(&developer_texturelogging);
7466         Cvar_RegisterVariable(&gl_lightmaps);
7467         Cvar_RegisterVariable(&r_test);
7468         Cvar_RegisterVariable(&r_glsl_saturation);
7469         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7470         Cvar_RegisterVariable(&r_framedatasize);
7471         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7472                 Cvar_SetValue("r_fullbrights", 0);
7473         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7474
7475         Cvar_RegisterVariable(&r_track_sprites);
7476         Cvar_RegisterVariable(&r_track_sprites_flags);
7477         Cvar_RegisterVariable(&r_track_sprites_scalew);
7478         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7479         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7480         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7481         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7482         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7483 }
7484
7485 extern void R_Textures_Init(void);
7486 extern void GL_Draw_Init(void);
7487 extern void GL_Main_Init(void);
7488 extern void R_Shadow_Init(void);
7489 extern void R_Sky_Init(void);
7490 extern void GL_Surf_Init(void);
7491 extern void R_Particles_Init(void);
7492 extern void R_Explosion_Init(void);
7493 extern void gl_backend_init(void);
7494 extern void Sbar_Init(void);
7495 extern void R_LightningBeams_Init(void);
7496 extern void Mod_RenderInit(void);
7497 extern void Font_Init(void);
7498
7499 void Render_Init(void)
7500 {
7501         gl_backend_init();
7502         R_Textures_Init();
7503         GL_Main_Init();
7504         Font_Init();
7505         GL_Draw_Init();
7506         R_Shadow_Init();
7507         R_Sky_Init();
7508         GL_Surf_Init();
7509         Sbar_Init();
7510         R_Particles_Init();
7511         R_Explosion_Init();
7512         R_LightningBeams_Init();
7513         Mod_RenderInit();
7514 }
7515
7516 /*
7517 ===============
7518 GL_Init
7519 ===============
7520 */
7521 extern char *ENGINE_EXTENSIONS;
7522 void GL_Init (void)
7523 {
7524         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7525         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7526         gl_version = (const char *)qglGetString(GL_VERSION);
7527         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7528
7529         if (!gl_extensions)
7530                 gl_extensions = "";
7531         if (!gl_platformextensions)
7532                 gl_platformextensions = "";
7533
7534         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7535         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7536         Con_Printf("GL_VERSION: %s\n", gl_version);
7537         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7538         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7539
7540         VID_CheckExtensions();
7541
7542         // LordHavoc: report supported extensions
7543         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7544
7545         // clear to black (loading plaque will be seen over this)
7546         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7547 }
7548
7549 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7550 {
7551         int i;
7552         mplane_t *p;
7553         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7554         {
7555                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7556                 if (i == 4)
7557                         continue;
7558                 p = r_refdef.view.frustum + i;
7559                 switch(p->signbits)
7560                 {
7561                 default:
7562                 case 0:
7563                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7564                                 return true;
7565                         break;
7566                 case 1:
7567                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7568                                 return true;
7569                         break;
7570                 case 2:
7571                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7572                                 return true;
7573                         break;
7574                 case 3:
7575                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7576                                 return true;
7577                         break;
7578                 case 4:
7579                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7580                                 return true;
7581                         break;
7582                 case 5:
7583                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7584                                 return true;
7585                         break;
7586                 case 6:
7587                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7588                                 return true;
7589                         break;
7590                 case 7:
7591                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7592                                 return true;
7593                         break;
7594                 }
7595         }
7596         return false;
7597 }
7598
7599 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7600 {
7601         int i;
7602         const mplane_t *p;
7603         for (i = 0;i < numplanes;i++)
7604         {
7605                 p = planes + i;
7606                 switch(p->signbits)
7607                 {
7608                 default:
7609                 case 0:
7610                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7611                                 return true;
7612                         break;
7613                 case 1:
7614                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7615                                 return true;
7616                         break;
7617                 case 2:
7618                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7619                                 return true;
7620                         break;
7621                 case 3:
7622                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7623                                 return true;
7624                         break;
7625                 case 4:
7626                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7627                                 return true;
7628                         break;
7629                 case 5:
7630                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7631                                 return true;
7632                         break;
7633                 case 6:
7634                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7635                                 return true;
7636                         break;
7637                 case 7:
7638                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7639                                 return true;
7640                         break;
7641                 }
7642         }
7643         return false;
7644 }
7645
7646 //==================================================================================
7647
7648 // LordHavoc: this stores temporary data used within the same frame
7649
7650 typedef struct r_framedata_mem_s
7651 {
7652         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7653         size_t size; // how much usable space
7654         size_t current; // how much space in use
7655         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7656         size_t wantedsize; // how much space was allocated
7657         unsigned char *data; // start of real data (16byte aligned)
7658 }
7659 r_framedata_mem_t;
7660
7661 static r_framedata_mem_t *r_framedata_mem;
7662
7663 void R_FrameData_Reset(void)
7664 {
7665         while (r_framedata_mem)
7666         {
7667                 r_framedata_mem_t *next = r_framedata_mem->purge;
7668                 Mem_Free(r_framedata_mem);
7669                 r_framedata_mem = next;
7670         }
7671 }
7672
7673 void R_FrameData_Resize(void)
7674 {
7675         size_t wantedsize;
7676         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7677         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7678         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7679         {
7680                 r_framedata_mem_t *newmem = Mem_Alloc(r_main_mempool, wantedsize);
7681                 newmem->wantedsize = wantedsize;
7682                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7683                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7684                 newmem->current = 0;
7685                 newmem->mark = 0;
7686                 newmem->purge = r_framedata_mem;
7687                 r_framedata_mem = newmem;
7688         }
7689 }
7690
7691 void R_FrameData_NewFrame(void)
7692 {
7693         R_FrameData_Resize();
7694         if (!r_framedata_mem)
7695                 return;
7696         // if we ran out of space on the last frame, free the old memory now
7697         while (r_framedata_mem->purge)
7698         {
7699                 // repeatedly remove the second item in the list, leaving only head
7700                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7701                 Mem_Free(r_framedata_mem->purge);
7702                 r_framedata_mem->purge = next;
7703         }
7704         // reset the current mem pointer
7705         r_framedata_mem->current = 0;
7706         r_framedata_mem->mark = 0;
7707 }
7708
7709 void *R_FrameData_Alloc(size_t size)
7710 {
7711         void *data;
7712
7713         // align to 16 byte boundary - the data pointer is already aligned, so we
7714         // only need to ensure the size of every allocation is also aligned
7715         size = (size + 15) & ~15;
7716
7717         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7718         {
7719                 // emergency - we ran out of space, allocate more memory
7720                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7721                 R_FrameData_Resize();
7722         }
7723
7724         data = r_framedata_mem->data + r_framedata_mem->current;
7725         r_framedata_mem->current += size;
7726
7727         // count the usage for stats
7728         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7729         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7730
7731         return (void *)data;
7732 }
7733
7734 void *R_FrameData_Store(size_t size, void *data)
7735 {
7736         void *d = R_FrameData_Alloc(size);
7737         if (d && data)
7738                 memcpy(d, data, size);
7739         return d;
7740 }
7741
7742 void R_FrameData_SetMark(void)
7743 {
7744         if (!r_framedata_mem)
7745                 return;
7746         r_framedata_mem->mark = r_framedata_mem->current;
7747 }
7748
7749 void R_FrameData_ReturnToMark(void)
7750 {
7751         if (!r_framedata_mem)
7752                 return;
7753         r_framedata_mem->current = r_framedata_mem->mark;
7754 }
7755
7756 //==================================================================================
7757
7758 // LordHavoc: animcache originally written by Echon, rewritten since then
7759
7760 /**
7761  * Animation cache prevents re-generating mesh data for an animated model
7762  * multiple times in one frame for lighting, shadowing, reflections, etc.
7763  */
7764
7765 void R_AnimCache_Free(void)
7766 {
7767 }
7768
7769 void R_AnimCache_ClearCache(void)
7770 {
7771         int i;
7772         entity_render_t *ent;
7773
7774         for (i = 0;i < r_refdef.scene.numentities;i++)
7775         {
7776                 ent = r_refdef.scene.entities[i];
7777                 ent->animcache_vertex3f = NULL;
7778                 ent->animcache_normal3f = NULL;
7779                 ent->animcache_svector3f = NULL;
7780                 ent->animcache_tvector3f = NULL;
7781                 ent->animcache_vertexmesh = NULL;
7782                 ent->animcache_vertex3fbuffer = NULL;
7783                 ent->animcache_vertexmeshbuffer = NULL;
7784         }
7785 }
7786
7787 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7788 {
7789         int i;
7790
7791         // check if we need the meshbuffers
7792         if (!vid.useinterleavedarrays)
7793                 return;
7794
7795         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7796                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7797         // TODO: upload vertex3f buffer?
7798         if (ent->animcache_vertexmesh)
7799         {
7800                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7801                 for (i = 0;i < numvertices;i++)
7802                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7803                 if (ent->animcache_svector3f)
7804                         for (i = 0;i < numvertices;i++)
7805                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7806                 if (ent->animcache_tvector3f)
7807                         for (i = 0;i < numvertices;i++)
7808                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7809                 if (ent->animcache_normal3f)
7810                         for (i = 0;i < numvertices;i++)
7811                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7812                 // TODO: upload vertexmeshbuffer?
7813         }
7814 }
7815
7816 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7817 {
7818         dp_model_t *model = ent->model;
7819         int numvertices;
7820         // see if it's already cached this frame
7821         if (ent->animcache_vertex3f)
7822         {
7823                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7824                 if (wantnormals || wanttangents)
7825                 {
7826                         if (ent->animcache_normal3f)
7827                                 wantnormals = false;
7828                         if (ent->animcache_svector3f)
7829                                 wanttangents = false;
7830                         if (wantnormals || wanttangents)
7831                         {
7832                                 numvertices = model->surfmesh.num_vertices;
7833                                 if (wantnormals)
7834                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7835                                 if (wanttangents)
7836                                 {
7837                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7838                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7839                                 }
7840                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7841                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
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                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7861                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7862         }
7863         return true;
7864 }
7865
7866 void R_AnimCache_CacheVisibleEntities(void)
7867 {
7868         int i;
7869         qboolean wantnormals = true;
7870         qboolean wanttangents = !r_showsurfaces.integer;
7871
7872         switch(vid.renderpath)
7873         {
7874         case RENDERPATH_GL20:
7875         case RENDERPATH_CGGL:
7876         case RENDERPATH_D3D9:
7877         case RENDERPATH_D3D10:
7878         case RENDERPATH_D3D11:
7879                 break;
7880         case RENDERPATH_GL13:
7881         case RENDERPATH_GL11:
7882                 wanttangents = false;
7883                 break;
7884         }
7885
7886         if (r_shownormals.integer)
7887                 wanttangents = wantnormals = true;
7888
7889         // TODO: thread this
7890         // NOTE: R_PrepareRTLights() also caches entities
7891
7892         for (i = 0;i < r_refdef.scene.numentities;i++)
7893                 if (r_refdef.viewcache.entityvisible[i])
7894                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7895 }
7896
7897 //==================================================================================
7898
7899 static void R_View_UpdateEntityLighting (void)
7900 {
7901         int i;
7902         entity_render_t *ent;
7903         vec3_t tempdiffusenormal, avg;
7904         vec_t f, fa, fd, fdd;
7905         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7906
7907         for (i = 0;i < r_refdef.scene.numentities;i++)
7908         {
7909                 ent = r_refdef.scene.entities[i];
7910
7911                 // skip unseen models
7912                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7913                         continue;
7914
7915                 // skip bsp models
7916                 if (ent->model && ent->model->brush.num_leafs)
7917                 {
7918                         // TODO: use modellight for r_ambient settings on world?
7919                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7920                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7921                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7922                         continue;
7923                 }
7924
7925                 // fetch the lighting from the worldmodel data
7926                 VectorClear(ent->modellight_ambient);
7927                 VectorClear(ent->modellight_diffuse);
7928                 VectorClear(tempdiffusenormal);
7929                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7930                 {
7931                         vec3_t org;
7932                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7933
7934                         // complete lightning for lit sprites
7935                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7936                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7937                         {
7938                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7939                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7940                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7941                         }
7942                         else
7943                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7944
7945                         if(ent->flags & RENDER_EQUALIZE)
7946                         {
7947                                 // first fix up ambient lighting...
7948                                 if(r_equalize_entities_minambient.value > 0)
7949                                 {
7950                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7951                                         if(fd > 0)
7952                                         {
7953                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7954                                                 if(fa < r_equalize_entities_minambient.value * fd)
7955                                                 {
7956                                                         // solve:
7957                                                         //   fa'/fd' = minambient
7958                                                         //   fa'+0.25*fd' = fa+0.25*fd
7959                                                         //   ...
7960                                                         //   fa' = fd' * minambient
7961                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7962                                                         //   ...
7963                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7964                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7965                                                         //   ...
7966                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7967                                                         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
7968                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7969                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7970                                                 }
7971                                         }
7972                                 }
7973
7974                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7975                                 {
7976                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7977                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7978                                         f = fa + 0.25 * fd;
7979                                         if(f > 0)
7980                                         {
7981                                                 // adjust brightness and saturation to target
7982                                                 avg[0] = avg[1] = avg[2] = fa / f;
7983                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7984                                                 avg[0] = avg[1] = avg[2] = fd / f;
7985                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7986                                         }
7987                                 }
7988                         }
7989                 }
7990                 else // highly rare
7991                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7992
7993                 // move the light direction into modelspace coordinates for lighting code
7994                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7995                 if(VectorLength2(ent->modellight_lightdir) == 0)
7996                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7997                 VectorNormalize(ent->modellight_lightdir);
7998         }
7999 }
8000
8001 #define MAX_LINEOFSIGHTTRACES 64
8002
8003 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8004 {
8005         int i;
8006         vec3_t boxmins, boxmaxs;
8007         vec3_t start;
8008         vec3_t end;
8009         dp_model_t *model = r_refdef.scene.worldmodel;
8010
8011         if (!model || !model->brush.TraceLineOfSight)
8012                 return true;
8013
8014         // expand the box a little
8015         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8016         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8017         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8018         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8019         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8020         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8021
8022         // return true if eye is inside enlarged box
8023         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8024                 return true;
8025
8026         // try center
8027         VectorCopy(eye, start);
8028         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8029         if (model->brush.TraceLineOfSight(model, start, end))
8030                 return true;
8031
8032         // try various random positions
8033         for (i = 0;i < numsamples;i++)
8034         {
8035                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8036                 if (model->brush.TraceLineOfSight(model, start, end))
8037                         return true;
8038         }
8039
8040         return false;
8041 }
8042
8043
8044 static void R_View_UpdateEntityVisible (void)
8045 {
8046         int i;
8047         int renderimask;
8048         int samples;
8049         entity_render_t *ent;
8050
8051         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8052                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8053                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8054                 :                                                          RENDER_EXTERIORMODEL;
8055         if (!r_drawviewmodel.integer)
8056                 renderimask |= RENDER_VIEWMODEL;
8057         if (!r_drawexteriormodel.integer)
8058                 renderimask |= RENDER_EXTERIORMODEL;
8059         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8060         {
8061                 // worldmodel can check visibility
8062                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8063                 for (i = 0;i < r_refdef.scene.numentities;i++)
8064                 {
8065                         ent = r_refdef.scene.entities[i];
8066                         if (!(ent->flags & renderimask))
8067                         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)))
8068                         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))
8069                                 r_refdef.viewcache.entityvisible[i] = true;
8070                 }
8071                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8072                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8073                 {
8074                         for (i = 0;i < r_refdef.scene.numentities;i++)
8075                         {
8076                                 ent = r_refdef.scene.entities[i];
8077                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8078                                 {
8079                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8080                                         if (samples < 0)
8081                                                 continue; // temp entities do pvs only
8082                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8083                                                 ent->last_trace_visibility = realtime;
8084                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8085                                                 r_refdef.viewcache.entityvisible[i] = 0;
8086                                 }
8087                         }
8088                 }
8089         }
8090         else
8091         {
8092                 // no worldmodel or it can't check visibility
8093                 for (i = 0;i < r_refdef.scene.numentities;i++)
8094                 {
8095                         ent = r_refdef.scene.entities[i];
8096                         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));
8097                 }
8098         }
8099 }
8100
8101 /// only used if skyrendermasked, and normally returns false
8102 int R_DrawBrushModelsSky (void)
8103 {
8104         int i, sky;
8105         entity_render_t *ent;
8106
8107         sky = false;
8108         for (i = 0;i < r_refdef.scene.numentities;i++)
8109         {
8110                 if (!r_refdef.viewcache.entityvisible[i])
8111                         continue;
8112                 ent = r_refdef.scene.entities[i];
8113                 if (!ent->model || !ent->model->DrawSky)
8114                         continue;
8115                 ent->model->DrawSky(ent);
8116                 sky = true;
8117         }
8118         return sky;
8119 }
8120
8121 static void R_DrawNoModel(entity_render_t *ent);
8122 static void R_DrawModels(void)
8123 {
8124         int i;
8125         entity_render_t *ent;
8126
8127         for (i = 0;i < r_refdef.scene.numentities;i++)
8128         {
8129                 if (!r_refdef.viewcache.entityvisible[i])
8130                         continue;
8131                 ent = r_refdef.scene.entities[i];
8132                 r_refdef.stats.entities++;
8133                 if (ent->model && ent->model->Draw != NULL)
8134                         ent->model->Draw(ent);
8135                 else
8136                         R_DrawNoModel(ent);
8137         }
8138 }
8139
8140 static void R_DrawModelsDepth(void)
8141 {
8142         int i;
8143         entity_render_t *ent;
8144
8145         for (i = 0;i < r_refdef.scene.numentities;i++)
8146         {
8147                 if (!r_refdef.viewcache.entityvisible[i])
8148                         continue;
8149                 ent = r_refdef.scene.entities[i];
8150                 if (ent->model && ent->model->DrawDepth != NULL)
8151                         ent->model->DrawDepth(ent);
8152         }
8153 }
8154
8155 static void R_DrawModelsDebug(void)
8156 {
8157         int i;
8158         entity_render_t *ent;
8159
8160         for (i = 0;i < r_refdef.scene.numentities;i++)
8161         {
8162                 if (!r_refdef.viewcache.entityvisible[i])
8163                         continue;
8164                 ent = r_refdef.scene.entities[i];
8165                 if (ent->model && ent->model->DrawDebug != NULL)
8166                         ent->model->DrawDebug(ent);
8167         }
8168 }
8169
8170 static void R_DrawModelsAddWaterPlanes(void)
8171 {
8172         int i;
8173         entity_render_t *ent;
8174
8175         for (i = 0;i < r_refdef.scene.numentities;i++)
8176         {
8177                 if (!r_refdef.viewcache.entityvisible[i])
8178                         continue;
8179                 ent = r_refdef.scene.entities[i];
8180                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8181                         ent->model->DrawAddWaterPlanes(ent);
8182         }
8183 }
8184
8185 static void R_View_SetFrustum(const int *scissor)
8186 {
8187         int i;
8188         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8189         vec3_t forward, left, up, origin, v;
8190
8191         if(scissor)
8192         {
8193                 // flipped x coordinates (because x points left here)
8194                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8195                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8196
8197                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8198                 switch(vid.renderpath)
8199                 {
8200                         case RENDERPATH_D3D9:
8201                         case RENDERPATH_D3D10:
8202                         case RENDERPATH_D3D11:
8203                                 // non-flipped y coordinates
8204                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8205                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8206                                 break;
8207                         case RENDERPATH_GL11:
8208                         case RENDERPATH_GL13:
8209                         case RENDERPATH_GL20:
8210                         case RENDERPATH_CGGL:
8211                                 // non-flipped y coordinates
8212                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8213                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8214                                 break;
8215                 }
8216         }
8217
8218         // we can't trust r_refdef.view.forward and friends in reflected scenes
8219         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8220
8221 #if 0
8222         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8223         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8224         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8225         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8226         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8227         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8228         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8229         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8230         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8231         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8232         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8233         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8234 #endif
8235
8236 #if 0
8237         zNear = r_refdef.nearclip;
8238         nudge = 1.0 - 1.0 / (1<<23);
8239         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8240         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8241         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8242         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8243         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8244         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8245         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8246         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8247 #endif
8248
8249
8250
8251 #if 0
8252         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8253         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8254         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8255         r_refdef.view.frustum[0].dist = m[15] - m[12];
8256
8257         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8258         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8259         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8260         r_refdef.view.frustum[1].dist = m[15] + m[12];
8261
8262         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8263         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8264         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8265         r_refdef.view.frustum[2].dist = m[15] - m[13];
8266
8267         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8268         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8269         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8270         r_refdef.view.frustum[3].dist = m[15] + m[13];
8271
8272         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8273         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8274         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8275         r_refdef.view.frustum[4].dist = m[15] - m[14];
8276
8277         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8278         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8279         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8280         r_refdef.view.frustum[5].dist = m[15] + m[14];
8281 #endif
8282
8283         if (r_refdef.view.useperspective)
8284         {
8285                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8286                 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]);
8287                 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]);
8288                 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]);
8289                 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]);
8290
8291                 // then the normals from the corners relative to origin
8292                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8293                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8294                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8295                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8296
8297                 // in a NORMAL view, forward cross left == up
8298                 // in a REFLECTED view, forward cross left == down
8299                 // so our cross products above need to be adjusted for a left handed coordinate system
8300                 CrossProduct(forward, left, v);
8301                 if(DotProduct(v, up) < 0)
8302                 {
8303                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8304                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8305                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8306                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8307                 }
8308
8309                 // Leaving those out was a mistake, those were in the old code, and they
8310                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8311                 // I couldn't reproduce it after adding those normalizations. --blub
8312                 VectorNormalize(r_refdef.view.frustum[0].normal);
8313                 VectorNormalize(r_refdef.view.frustum[1].normal);
8314                 VectorNormalize(r_refdef.view.frustum[2].normal);
8315                 VectorNormalize(r_refdef.view.frustum[3].normal);
8316
8317                 // make the corners absolute
8318                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8319                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8320                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8321                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8322
8323                 // one more normal
8324                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8325
8326                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8327                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8328                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8329                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8330                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8331         }
8332         else
8333         {
8334                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8335                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8336                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8337                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8338                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8339                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8340                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8341                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8342                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8343                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8344         }
8345         r_refdef.view.numfrustumplanes = 5;
8346
8347         if (r_refdef.view.useclipplane)
8348         {
8349                 r_refdef.view.numfrustumplanes = 6;
8350                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8351         }
8352
8353         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8354                 PlaneClassify(r_refdef.view.frustum + i);
8355
8356         // LordHavoc: note to all quake engine coders, Quake had a special case
8357         // for 90 degrees which assumed a square view (wrong), so I removed it,
8358         // Quake2 has it disabled as well.
8359
8360         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8361         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8362         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8363         //PlaneClassify(&frustum[0]);
8364
8365         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8366         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8367         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8368         //PlaneClassify(&frustum[1]);
8369
8370         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8371         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8372         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8373         //PlaneClassify(&frustum[2]);
8374
8375         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8376         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8377         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8378         //PlaneClassify(&frustum[3]);
8379
8380         // nearclip plane
8381         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8382         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8383         //PlaneClassify(&frustum[4]);
8384 }
8385
8386 void R_View_UpdateWithScissor(const int *myscissor)
8387 {
8388         R_Main_ResizeViewCache();
8389         R_View_SetFrustum(myscissor);
8390         R_View_WorldVisibility(r_refdef.view.useclipplane);
8391         R_View_UpdateEntityVisible();
8392         R_View_UpdateEntityLighting();
8393 }
8394
8395 void R_View_Update(void)
8396 {
8397         R_Main_ResizeViewCache();
8398         R_View_SetFrustum(NULL);
8399         R_View_WorldVisibility(r_refdef.view.useclipplane);
8400         R_View_UpdateEntityVisible();
8401         R_View_UpdateEntityLighting();
8402 }
8403
8404 void R_SetupView(qboolean allowwaterclippingplane)
8405 {
8406         const float *customclipplane = NULL;
8407         float plane[4];
8408         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8409         {
8410                 // LordHavoc: couldn't figure out how to make this approach the
8411                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8412                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8413                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8414                         dist = r_refdef.view.clipplane.dist;
8415                 plane[0] = r_refdef.view.clipplane.normal[0];
8416                 plane[1] = r_refdef.view.clipplane.normal[1];
8417                 plane[2] = r_refdef.view.clipplane.normal[2];
8418                 plane[3] = dist;
8419                 customclipplane = plane;
8420         }
8421
8422         if (!r_refdef.view.useperspective)
8423                 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);
8424         else if (vid.stencil && r_useinfinitefarclip.integer)
8425                 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);
8426         else
8427                 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);
8428         R_SetViewport(&r_refdef.view.viewport);
8429 }
8430
8431 void R_EntityMatrix(const matrix4x4_t *matrix)
8432 {
8433         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8434         {
8435                 gl_modelmatrixchanged = false;
8436                 gl_modelmatrix = *matrix;
8437                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8438                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8439                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8440                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8441                 CHECKGLERROR
8442                 switch(vid.renderpath)
8443                 {
8444                 case RENDERPATH_D3D9:
8445 #ifdef SUPPORTD3D
8446                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8447                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8448 #endif
8449                         break;
8450                 case RENDERPATH_D3D10:
8451                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8452                         break;
8453                 case RENDERPATH_D3D11:
8454                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8455                         break;
8456                 case RENDERPATH_GL20:
8457                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8458                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8459                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8460                         break;
8461                 case RENDERPATH_CGGL:
8462 #ifdef SUPPORTCG
8463                         CHECKCGERROR
8464                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8465                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8466                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8467 #endif
8468                         break;
8469                 case RENDERPATH_GL13:
8470                 case RENDERPATH_GL11:
8471                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8472                         break;
8473                 }
8474         }
8475 }
8476
8477 void R_ResetViewRendering2D(void)
8478 {
8479         r_viewport_t viewport;
8480         DrawQ_Finish();
8481
8482         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8483         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);
8484         R_SetViewport(&viewport);
8485         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8486         GL_Color(1, 1, 1, 1);
8487         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8488         GL_BlendFunc(GL_ONE, GL_ZERO);
8489         GL_AlphaTest(false);
8490         GL_ScissorTest(false);
8491         GL_DepthMask(false);
8492         GL_DepthRange(0, 1);
8493         GL_DepthTest(false);
8494         GL_DepthFunc(GL_LEQUAL);
8495         R_EntityMatrix(&identitymatrix);
8496         R_Mesh_ResetTextureState();
8497         GL_PolygonOffset(0, 0);
8498         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8499         switch(vid.renderpath)
8500         {
8501         case RENDERPATH_GL11:
8502         case RENDERPATH_GL13:
8503         case RENDERPATH_GL20:
8504         case RENDERPATH_CGGL:
8505                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8506                 break;
8507         case RENDERPATH_D3D9:
8508         case RENDERPATH_D3D10:
8509         case RENDERPATH_D3D11:
8510                 break;
8511         }
8512         GL_CullFace(GL_NONE);
8513 }
8514
8515 void R_ResetViewRendering3D(void)
8516 {
8517         DrawQ_Finish();
8518
8519         R_SetupView(true);
8520         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8521         GL_Color(1, 1, 1, 1);
8522         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8523         GL_BlendFunc(GL_ONE, GL_ZERO);
8524         GL_AlphaTest(false);
8525         GL_ScissorTest(true);
8526         GL_DepthMask(true);
8527         GL_DepthRange(0, 1);
8528         GL_DepthTest(true);
8529         GL_DepthFunc(GL_LEQUAL);
8530         R_EntityMatrix(&identitymatrix);
8531         R_Mesh_ResetTextureState();
8532         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8533         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8534         switch(vid.renderpath)
8535         {
8536         case RENDERPATH_GL11:
8537         case RENDERPATH_GL13:
8538         case RENDERPATH_GL20:
8539         case RENDERPATH_CGGL:
8540                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8541                 break;
8542         case RENDERPATH_D3D9:
8543         case RENDERPATH_D3D10:
8544         case RENDERPATH_D3D11:
8545                 break;
8546         }
8547         GL_CullFace(r_refdef.view.cullface_back);
8548 }
8549
8550 /*
8551 ================
8552 R_RenderView_UpdateViewVectors
8553 ================
8554 */
8555 static void R_RenderView_UpdateViewVectors(void)
8556 {
8557         // break apart the view matrix into vectors for various purposes
8558         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8559         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8560         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8561         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8562         // make an inverted copy of the view matrix for tracking sprites
8563         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8564 }
8565
8566 void R_RenderScene(void);
8567 void R_RenderWaterPlanes(void);
8568
8569 static void R_Water_StartFrame(void)
8570 {
8571         int i;
8572         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8573         r_waterstate_waterplane_t *p;
8574
8575         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8576                 return;
8577
8578         switch(vid.renderpath)
8579         {
8580         case RENDERPATH_GL20:
8581         case RENDERPATH_CGGL:
8582         case RENDERPATH_D3D9:
8583         case RENDERPATH_D3D10:
8584         case RENDERPATH_D3D11:
8585                 break;
8586         case RENDERPATH_GL13:
8587         case RENDERPATH_GL11:
8588                 return;
8589         }
8590
8591         // set waterwidth and waterheight to the water resolution that will be
8592         // used (often less than the screen resolution for faster rendering)
8593         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8594         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8595
8596         // calculate desired texture sizes
8597         // can't use water if the card does not support the texture size
8598         if (!r_water.integer || r_showsurfaces.integer)
8599                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8600         else if (vid.support.arb_texture_non_power_of_two)
8601         {
8602                 texturewidth = waterwidth;
8603                 textureheight = waterheight;
8604                 camerawidth = waterwidth;
8605                 cameraheight = waterheight;
8606         }
8607         else
8608         {
8609                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8610                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8611                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8612                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8613         }
8614
8615         // allocate textures as needed
8616         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8617         {
8618                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8619                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8620                 {
8621                         if (p->texture_refraction)
8622                                 R_FreeTexture(p->texture_refraction);
8623                         p->texture_refraction = NULL;
8624                         if (p->texture_reflection)
8625                                 R_FreeTexture(p->texture_reflection);
8626                         p->texture_reflection = NULL;
8627                         if (p->texture_camera)
8628                                 R_FreeTexture(p->texture_camera);
8629                         p->texture_camera = NULL;
8630                 }
8631                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8632                 r_waterstate.texturewidth = texturewidth;
8633                 r_waterstate.textureheight = textureheight;
8634                 r_waterstate.camerawidth = camerawidth;
8635                 r_waterstate.cameraheight = cameraheight;
8636         }
8637
8638         if (r_waterstate.texturewidth)
8639         {
8640                 r_waterstate.enabled = true;
8641
8642                 // when doing a reduced render (HDR) we want to use a smaller area
8643                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8644                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8645
8646                 // set up variables that will be used in shader setup
8647                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8648                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8649                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8650                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8651         }
8652
8653         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8654         r_waterstate.numwaterplanes = 0;
8655 }
8656
8657 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8658 {
8659         int triangleindex, planeindex;
8660         const int *e;
8661         vec3_t vert[3];
8662         vec3_t normal;
8663         vec3_t center;
8664         mplane_t plane;
8665         r_waterstate_waterplane_t *p;
8666         texture_t *t = R_GetCurrentTexture(surface->texture);
8667
8668         // just use the first triangle with a valid normal for any decisions
8669         VectorClear(normal);
8670         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8671         {
8672                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8673                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8674                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8675                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8676                 if (VectorLength2(normal) >= 0.001)
8677                         break;
8678         }
8679
8680         VectorCopy(normal, plane.normal);
8681         VectorNormalize(plane.normal);
8682         plane.dist = DotProduct(vert[0], plane.normal);
8683         PlaneClassify(&plane);
8684         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8685         {
8686                 // skip backfaces (except if nocullface is set)
8687                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8688                         return;
8689                 VectorNegate(plane.normal, plane.normal);
8690                 plane.dist *= -1;
8691                 PlaneClassify(&plane);
8692         }
8693
8694
8695         // find a matching plane if there is one
8696         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8697                 if(p->camera_entity == t->camera_entity)
8698                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8699                                 break;
8700         if (planeindex >= r_waterstate.maxwaterplanes)
8701                 return; // nothing we can do, out of planes
8702
8703         // if this triangle does not fit any known plane rendered this frame, add one
8704         if (planeindex >= r_waterstate.numwaterplanes)
8705         {
8706                 // store the new plane
8707                 r_waterstate.numwaterplanes++;
8708                 p->plane = plane;
8709                 // clear materialflags and pvs
8710                 p->materialflags = 0;
8711                 p->pvsvalid = false;
8712                 p->camera_entity = t->camera_entity;
8713                 VectorCopy(surface->mins, p->mins);
8714                 VectorCopy(surface->maxs, p->maxs);
8715         }
8716         else
8717         {
8718                 // merge mins/maxs
8719                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8720                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8721                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8722                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8723                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8724                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8725         }
8726         // merge this surface's materialflags into the waterplane
8727         p->materialflags |= t->currentmaterialflags;
8728         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8729         {
8730                 // merge this surface's PVS into the waterplane
8731                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8732                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8733                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8734                 {
8735                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8736                         p->pvsvalid = true;
8737                 }
8738         }
8739 }
8740
8741 static void R_Water_ProcessPlanes(void)
8742 {
8743         int myscissor[4];
8744         r_refdef_view_t originalview;
8745         r_refdef_view_t myview;
8746         int planeindex;
8747         r_waterstate_waterplane_t *p;
8748         vec3_t visorigin;
8749
8750         originalview = r_refdef.view;
8751
8752         // make sure enough textures are allocated
8753         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8754         {
8755                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8756                 {
8757                         if (!p->texture_refraction)
8758                                 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);
8759                         if (!p->texture_refraction)
8760                                 goto error;
8761                 }
8762                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8763                 {
8764                         if (!p->texture_camera)
8765                                 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);
8766                         if (!p->texture_camera)
8767                                 goto error;
8768                 }
8769
8770                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8771                 {
8772                         if (!p->texture_reflection)
8773                                 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);
8774                         if (!p->texture_reflection)
8775                                 goto error;
8776                 }
8777         }
8778
8779         // render views
8780         r_refdef.view = originalview;
8781         r_refdef.view.showdebug = false;
8782         r_refdef.view.width = r_waterstate.waterwidth;
8783         r_refdef.view.height = r_waterstate.waterheight;
8784         r_refdef.view.useclipplane = true;
8785         myview = r_refdef.view;
8786         r_waterstate.renderingscene = true;
8787         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8788         {
8789                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8790                 {
8791                         r_refdef.view = myview;
8792                         if(r_water_scissormode.integer)
8793                         {
8794                                 R_SetupView(true);
8795                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8796                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8797                         }
8798
8799                         // render reflected scene and copy into texture
8800                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8801                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8802                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8803                         r_refdef.view.clipplane = p->plane;
8804
8805                         // reverse the cullface settings for this render
8806                         r_refdef.view.cullface_front = GL_FRONT;
8807                         r_refdef.view.cullface_back = GL_BACK;
8808                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8809                         {
8810                                 r_refdef.view.usecustompvs = true;
8811                                 if (p->pvsvalid)
8812                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8813                                 else
8814                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8815                         }
8816
8817                         R_ResetViewRendering3D();
8818                         R_ClearScreen(r_refdef.fogenabled);
8819                         if(r_water_scissormode.integer & 2)
8820                                 R_View_UpdateWithScissor(myscissor);
8821                         else
8822                                 R_View_Update();
8823                         if(r_water_scissormode.integer & 1)
8824                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8825                         R_RenderScene();
8826
8827                         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);
8828                 }
8829
8830                 // render the normal view scene and copy into texture
8831                 // (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)
8832                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8833                 {
8834                         r_refdef.view = myview;
8835                         if(r_water_scissormode.integer)
8836                         {
8837                                 R_SetupView(true);
8838                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8839                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8840                         }
8841
8842                         r_waterstate.renderingrefraction = true;
8843
8844                         r_refdef.view.clipplane = p->plane;
8845                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8846                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8847
8848                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8849                         {
8850                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8851                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8852                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8853                                 R_RenderView_UpdateViewVectors();
8854                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8855                                 {
8856                                         r_refdef.view.usecustompvs = true;
8857                                         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);
8858                                 }
8859                         }
8860
8861                         PlaneClassify(&r_refdef.view.clipplane);
8862
8863                         R_ResetViewRendering3D();
8864                         R_ClearScreen(r_refdef.fogenabled);
8865                         if(r_water_scissormode.integer & 2)
8866                                 R_View_UpdateWithScissor(myscissor);
8867                         else
8868                                 R_View_Update();
8869                         if(r_water_scissormode.integer & 1)
8870                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8871                         R_RenderScene();
8872
8873                         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);
8874                         r_waterstate.renderingrefraction = false;
8875                 }
8876                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8877                 {
8878                         r_refdef.view = myview;
8879
8880                         r_refdef.view.clipplane = p->plane;
8881                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8882                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8883
8884                         r_refdef.view.width = r_waterstate.camerawidth;
8885                         r_refdef.view.height = r_waterstate.cameraheight;
8886                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8887                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8888
8889                         if(p->camera_entity)
8890                         {
8891                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8892                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8893                         }
8894
8895                         // note: all of the view is used for displaying... so
8896                         // there is no use in scissoring
8897
8898                         // reverse the cullface settings for this render
8899                         r_refdef.view.cullface_front = GL_FRONT;
8900                         r_refdef.view.cullface_back = GL_BACK;
8901                         // also reverse the view matrix
8902                         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
8903                         R_RenderView_UpdateViewVectors();
8904                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8905                         {
8906                                 r_refdef.view.usecustompvs = true;
8907                                 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);
8908                         }
8909                         
8910                         // camera needs no clipplane
8911                         r_refdef.view.useclipplane = false;
8912
8913                         PlaneClassify(&r_refdef.view.clipplane);
8914
8915                         R_ResetViewRendering3D();
8916                         R_ClearScreen(r_refdef.fogenabled);
8917                         R_View_Update();
8918                         R_RenderScene();
8919
8920                         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);
8921                         r_waterstate.renderingrefraction = false;
8922                 }
8923
8924         }
8925         r_waterstate.renderingscene = false;
8926         r_refdef.view = originalview;
8927         R_ResetViewRendering3D();
8928         R_ClearScreen(r_refdef.fogenabled);
8929         R_View_Update();
8930         return;
8931 error:
8932         r_refdef.view = originalview;
8933         r_waterstate.renderingscene = false;
8934         Cvar_SetValueQuick(&r_water, 0);
8935         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8936         return;
8937 }
8938
8939 void R_Bloom_StartFrame(void)
8940 {
8941         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8942
8943         switch(vid.renderpath)
8944         {
8945         case RENDERPATH_GL20:
8946         case RENDERPATH_CGGL:
8947         case RENDERPATH_D3D9:
8948         case RENDERPATH_D3D10:
8949         case RENDERPATH_D3D11:
8950                 break;
8951         case RENDERPATH_GL13:
8952         case RENDERPATH_GL11:
8953                 return;
8954         }
8955
8956         // set bloomwidth and bloomheight to the bloom resolution that will be
8957         // used (often less than the screen resolution for faster rendering)
8958         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8959         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8960         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8961         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8962         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8963
8964         // calculate desired texture sizes
8965         if (vid.support.arb_texture_non_power_of_two)
8966         {
8967                 screentexturewidth = r_refdef.view.width;
8968                 screentextureheight = r_refdef.view.height;
8969                 bloomtexturewidth = r_bloomstate.bloomwidth;
8970                 bloomtextureheight = r_bloomstate.bloomheight;
8971         }
8972         else
8973         {
8974                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8975                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8976                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8977                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8978         }
8979
8980         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))
8981         {
8982                 Cvar_SetValueQuick(&r_hdr, 0);
8983                 Cvar_SetValueQuick(&r_bloom, 0);
8984                 Cvar_SetValueQuick(&r_motionblur, 0);
8985                 Cvar_SetValueQuick(&r_damageblur, 0);
8986         }
8987
8988         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)))
8989                 screentexturewidth = screentextureheight = 0;
8990         if (!r_hdr.integer && !r_bloom.integer)
8991                 bloomtexturewidth = bloomtextureheight = 0;
8992
8993         // allocate textures as needed
8994         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8995         {
8996                 if (r_bloomstate.texture_screen)
8997                         R_FreeTexture(r_bloomstate.texture_screen);
8998                 r_bloomstate.texture_screen = NULL;
8999                 r_bloomstate.screentexturewidth = screentexturewidth;
9000                 r_bloomstate.screentextureheight = screentextureheight;
9001                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9002                         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);
9003         }
9004         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9005         {
9006                 if (r_bloomstate.texture_bloom)
9007                         R_FreeTexture(r_bloomstate.texture_bloom);
9008                 r_bloomstate.texture_bloom = NULL;
9009                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9010                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9011                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9012                         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);
9013         }
9014
9015         // when doing a reduced render (HDR) we want to use a smaller area
9016         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9017         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9018         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9019         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9021
9022         // set up a texcoord array for the full resolution screen image
9023         // (we have to keep this around to copy back during final render)
9024         r_bloomstate.screentexcoord2f[0] = 0;
9025         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9026         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9027         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9028         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9029         r_bloomstate.screentexcoord2f[5] = 0;
9030         r_bloomstate.screentexcoord2f[6] = 0;
9031         r_bloomstate.screentexcoord2f[7] = 0;
9032
9033         // set up a texcoord array for the reduced resolution bloom image
9034         // (which will be additive blended over the screen image)
9035         r_bloomstate.bloomtexcoord2f[0] = 0;
9036         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9037         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9038         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9039         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9040         r_bloomstate.bloomtexcoord2f[5] = 0;
9041         r_bloomstate.bloomtexcoord2f[6] = 0;
9042         r_bloomstate.bloomtexcoord2f[7] = 0;
9043
9044         switch(vid.renderpath)
9045         {
9046         case RENDERPATH_GL11:
9047         case RENDERPATH_GL13:
9048         case RENDERPATH_GL20:
9049         case RENDERPATH_CGGL:
9050                 break;
9051         case RENDERPATH_D3D9:
9052         case RENDERPATH_D3D10:
9053         case RENDERPATH_D3D11:
9054                 {
9055                         int i;
9056                         for (i = 0;i < 4;i++)
9057                         {
9058                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9059                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9060                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9061                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9062                         }
9063                 }
9064                 break;
9065         }
9066
9067         if (r_hdr.integer || r_bloom.integer)
9068         {
9069                 r_bloomstate.enabled = true;
9070                 r_bloomstate.hdr = r_hdr.integer != 0;
9071         }
9072
9073         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);
9074 }
9075
9076 void R_Bloom_CopyBloomTexture(float colorscale)
9077 {
9078         r_refdef.stats.bloom++;
9079
9080         // scale down screen texture to the bloom texture size
9081         CHECKGLERROR
9082         R_SetViewport(&r_bloomstate.viewport);
9083         GL_BlendFunc(GL_ONE, GL_ZERO);
9084         GL_Color(colorscale, colorscale, colorscale, 1);
9085         // 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...
9086         switch(vid.renderpath)
9087         {
9088         case RENDERPATH_GL11:
9089         case RENDERPATH_GL13:
9090         case RENDERPATH_GL20:
9091         case RENDERPATH_CGGL:
9092                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9093                 break;
9094         case RENDERPATH_D3D9:
9095         case RENDERPATH_D3D10:
9096         case RENDERPATH_D3D11:
9097                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9098                 break;
9099         }
9100         // TODO: do boxfilter scale-down in shader?
9101         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9102         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9103         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9104
9105         // we now have a bloom image in the framebuffer
9106         // copy it into the bloom image texture for later processing
9107         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);
9108         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9109 }
9110
9111 void R_Bloom_CopyHDRTexture(void)
9112 {
9113         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);
9114         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9115 }
9116
9117 void R_Bloom_MakeTexture(void)
9118 {
9119         int x, range, dir;
9120         float xoffset, yoffset, r, brighten;
9121
9122         r_refdef.stats.bloom++;
9123
9124         R_ResetViewRendering2D();
9125
9126         // we have a bloom image in the framebuffer
9127         CHECKGLERROR
9128         R_SetViewport(&r_bloomstate.viewport);
9129
9130         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9131         {
9132                 x *= 2;
9133                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9134                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9135                 GL_Color(r,r,r,1);
9136                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9137                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9138                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9139                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9140
9141                 // copy the vertically blurred bloom view to a texture
9142                 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);
9143                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9144         }
9145
9146         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9147         brighten = r_bloom_brighten.value;
9148         if (r_hdr.integer)
9149                 brighten *= r_hdr_range.value;
9150         brighten = sqrt(brighten);
9151         if(range >= 1)
9152                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9153         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9154
9155         for (dir = 0;dir < 2;dir++)
9156         {
9157                 // blend on at multiple vertical offsets to achieve a vertical blur
9158                 // TODO: do offset blends using GLSL
9159                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9160                 GL_BlendFunc(GL_ONE, GL_ZERO);
9161                 for (x = -range;x <= range;x++)
9162                 {
9163                         if (!dir){xoffset = 0;yoffset = x;}
9164                         else {xoffset = x;yoffset = 0;}
9165                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9166                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9167                         // compute a texcoord array with the specified x and y offset
9168                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9169                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9171                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9172                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9173                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9174                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9175                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9176                         // this r value looks like a 'dot' particle, fading sharply to
9177                         // black at the edges
9178                         // (probably not realistic but looks good enough)
9179                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9180                         //r = brighten/(range*2+1);
9181                         r = brighten / (range * 2 + 1);
9182                         if(range >= 1)
9183                                 r *= (1 - x*x/(float)(range*range));
9184                         GL_Color(r, r, r, 1);
9185                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9186                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9187                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9188                         GL_BlendFunc(GL_ONE, GL_ONE);
9189                 }
9190
9191                 // copy the vertically blurred bloom view to a texture
9192                 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);
9193                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9194         }
9195 }
9196
9197 void R_HDR_RenderBloomTexture(void)
9198 {
9199         int oldwidth, oldheight;
9200         float oldcolorscale;
9201         int oldwaterstate;
9202
9203         oldwaterstate = r_waterstate.enabled;
9204         oldcolorscale = r_refdef.view.colorscale;
9205         oldwidth = r_refdef.view.width;
9206         oldheight = r_refdef.view.height;
9207         r_refdef.view.width = r_bloomstate.bloomwidth;
9208         r_refdef.view.height = r_bloomstate.bloomheight;
9209
9210         if(r_hdr.integer < 2)
9211                 r_waterstate.enabled = false;
9212
9213         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9214         // TODO: add exposure compensation features
9215         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9216
9217         r_refdef.view.showdebug = false;
9218         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9219
9220         R_ResetViewRendering3D();
9221
9222         R_ClearScreen(r_refdef.fogenabled);
9223         if (r_timereport_active)
9224                 R_TimeReport("HDRclear");
9225
9226         R_View_Update();
9227         if (r_timereport_active)
9228                 R_TimeReport("visibility");
9229
9230         // only do secondary renders with HDR if r_hdr is 2 or higher
9231         r_waterstate.numwaterplanes = 0;
9232         if (r_waterstate.enabled)
9233                 R_RenderWaterPlanes();
9234
9235         r_refdef.view.showdebug = true;
9236         R_RenderScene();
9237         r_waterstate.numwaterplanes = 0;
9238
9239         R_ResetViewRendering2D();
9240
9241         R_Bloom_CopyHDRTexture();
9242         R_Bloom_MakeTexture();
9243
9244         // restore the view settings
9245         r_waterstate.enabled = oldwaterstate;
9246         r_refdef.view.width = oldwidth;
9247         r_refdef.view.height = oldheight;
9248         r_refdef.view.colorscale = oldcolorscale;
9249
9250         R_ResetViewRendering3D();
9251
9252         R_ClearScreen(r_refdef.fogenabled);
9253         if (r_timereport_active)
9254                 R_TimeReport("viewclear");
9255 }
9256
9257 static void R_BlendView(void)
9258 {
9259         unsigned int permutation;
9260         float uservecs[4][4];
9261
9262         switch (vid.renderpath)
9263         {
9264         case RENDERPATH_GL20:
9265         case RENDERPATH_CGGL:
9266         case RENDERPATH_D3D9:
9267         case RENDERPATH_D3D10:
9268         case RENDERPATH_D3D11:
9269                 permutation =
9270                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9271                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9272                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9273                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9274                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9275
9276                 if (r_bloomstate.texture_screen)
9277                 {
9278                         // make sure the buffer is available
9279                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9280
9281                         R_ResetViewRendering2D();
9282
9283                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9284                         {
9285                                 // declare variables
9286                                 float speed;
9287                                 static float avgspeed;
9288
9289                                 speed = VectorLength(cl.movement_velocity);
9290
9291                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9292                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9293
9294                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9295                                 speed = bound(0, speed, 1);
9296                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9297
9298                                 // calculate values into a standard alpha
9299                                 cl.motionbluralpha = 1 - exp(-
9300                                                 (
9301                                                  (r_motionblur.value * speed / 80)
9302                                                  +
9303                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9304                                                 )
9305                                                 /
9306                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9307                                            );
9308
9309                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9310                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9311                                 // apply the blur
9312                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9313                                 {
9314                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9315                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9316                                         switch(vid.renderpath)
9317                                         {
9318                                         case RENDERPATH_GL11:
9319                                         case RENDERPATH_GL13:
9320                                         case RENDERPATH_GL20:
9321                                         case RENDERPATH_CGGL:
9322                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9323                                                 break;
9324                                         case RENDERPATH_D3D9:
9325                                         case RENDERPATH_D3D10:
9326                                         case RENDERPATH_D3D11:
9327                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9328                                                 break;
9329                                         }
9330                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9331                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9332                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9333                                 }
9334                         }
9335
9336                         // copy view into the screen texture
9337                         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);
9338                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9339                 }
9340                 else if (!r_bloomstate.texture_bloom)
9341                 {
9342                         // we may still have to do view tint...
9343                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9344                         {
9345                                 // apply a color tint to the whole view
9346                                 R_ResetViewRendering2D();
9347                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9348                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9349                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9350                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9351                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9352                         }
9353                         break; // no screen processing, no bloom, skip it
9354                 }
9355
9356                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9357                 {
9358                         // render simple bloom effect
9359                         // copy the screen and shrink it and darken it for the bloom process
9360                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9361                         // make the bloom texture
9362                         R_Bloom_MakeTexture();
9363                 }
9364
9365 #if _MSC_VER >= 1400
9366 #define sscanf sscanf_s
9367 #endif
9368                 memset(uservecs, 0, sizeof(uservecs));
9369                 if (r_glsl_postprocess_uservec1_enable.integer)
9370                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9371                 if (r_glsl_postprocess_uservec2_enable.integer)
9372                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9373                 if (r_glsl_postprocess_uservec3_enable.integer)
9374                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9375                 if (r_glsl_postprocess_uservec4_enable.integer)
9376                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9377
9378                 R_ResetViewRendering2D();
9379                 GL_Color(1, 1, 1, 1);
9380                 GL_BlendFunc(GL_ONE, GL_ZERO);
9381
9382                 switch(vid.renderpath)
9383                 {
9384                 case RENDERPATH_GL20:
9385                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9386                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9387                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9388                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9389                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9390                         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]);
9391                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9392                         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]);
9393                         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]);
9394                         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]);
9395                         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]);
9396                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9397                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9398                         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);
9399                         break;
9400                 case RENDERPATH_CGGL:
9401 #ifdef SUPPORTCG
9402                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9403                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9404                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9405                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9406                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9407                         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
9408                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9409                         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
9410                         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
9411                         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
9412                         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
9413                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9414                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9415                         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);
9416 #endif
9417                         break;
9418                 case RENDERPATH_D3D9:
9419 #ifdef SUPPORTD3D
9420                         // 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...
9421                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9422                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9423                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9424                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9425                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9426                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9427                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9428                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9429                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9430                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9431                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9432                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9433                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9434                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9435 #endif
9436                         break;
9437                 case RENDERPATH_D3D10:
9438                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9439                         break;
9440                 case RENDERPATH_D3D11:
9441                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9442                         break;
9443                 default:
9444                         break;
9445                 }
9446                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9447                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9448                 break;
9449         case RENDERPATH_GL13:
9450         case RENDERPATH_GL11:
9451                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9452                 {
9453                         // apply a color tint to the whole view
9454                         R_ResetViewRendering2D();
9455                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9456                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9457                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9458                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9459                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9460                 }
9461                 break;
9462         }
9463 }
9464
9465 matrix4x4_t r_waterscrollmatrix;
9466
9467 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9468 {
9469         if (r_refdef.fog_density)
9470         {
9471                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9472                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9473                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9474
9475                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9476                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9477                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9478                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9479
9480                 {
9481                         vec3_t fogvec;
9482                         VectorCopy(r_refdef.fogcolor, fogvec);
9483                         //   color.rgb *= ContrastBoost * SceneBrightness;
9484                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9485                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9486                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9487                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9488                 }
9489         }
9490 }
9491
9492 void R_UpdateVariables(void)
9493 {
9494         R_Textures_Frame();
9495
9496         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9497
9498         r_refdef.farclip = r_farclip_base.value;
9499         if (r_refdef.scene.worldmodel)
9500                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9501         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9502
9503         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9504                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9505         r_refdef.polygonfactor = 0;
9506         r_refdef.polygonoffset = 0;
9507         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9508         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9509
9510         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9511         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9512         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9513         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9514         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9515         if (FAKELIGHT_ENABLED)
9516         {
9517                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9518         }
9519         if (r_showsurfaces.integer)
9520         {
9521                 r_refdef.scene.rtworld = false;
9522                 r_refdef.scene.rtworldshadows = false;
9523                 r_refdef.scene.rtdlight = false;
9524                 r_refdef.scene.rtdlightshadows = false;
9525                 r_refdef.lightmapintensity = 0;
9526         }
9527
9528         if (gamemode == GAME_NEHAHRA)
9529         {
9530                 if (gl_fogenable.integer)
9531                 {
9532                         r_refdef.oldgl_fogenable = true;
9533                         r_refdef.fog_density = gl_fogdensity.value;
9534                         r_refdef.fog_red = gl_fogred.value;
9535                         r_refdef.fog_green = gl_foggreen.value;
9536                         r_refdef.fog_blue = gl_fogblue.value;
9537                         r_refdef.fog_alpha = 1;
9538                         r_refdef.fog_start = 0;
9539                         r_refdef.fog_end = gl_skyclip.value;
9540                         r_refdef.fog_height = 1<<30;
9541                         r_refdef.fog_fadedepth = 128;
9542                 }
9543                 else if (r_refdef.oldgl_fogenable)
9544                 {
9545                         r_refdef.oldgl_fogenable = false;
9546                         r_refdef.fog_density = 0;
9547                         r_refdef.fog_red = 0;
9548                         r_refdef.fog_green = 0;
9549                         r_refdef.fog_blue = 0;
9550                         r_refdef.fog_alpha = 0;
9551                         r_refdef.fog_start = 0;
9552                         r_refdef.fog_end = 0;
9553                         r_refdef.fog_height = 1<<30;
9554                         r_refdef.fog_fadedepth = 128;
9555                 }
9556         }
9557
9558         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9559         r_refdef.fog_start = max(0, r_refdef.fog_start);
9560         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9561
9562         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9563
9564         if (r_refdef.fog_density && r_drawfog.integer)
9565         {
9566                 r_refdef.fogenabled = true;
9567                 // this is the point where the fog reaches 0.9986 alpha, which we
9568                 // consider a good enough cutoff point for the texture
9569                 // (0.9986 * 256 == 255.6)
9570                 if (r_fog_exp2.integer)
9571                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9572                 else
9573                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9574                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9575                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9576                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9577                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9578                         R_BuildFogHeightTexture();
9579                 // fog color was already set
9580                 // update the fog texture
9581                 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)
9582                         R_BuildFogTexture();
9583                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9584                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9585         }
9586         else
9587                 r_refdef.fogenabled = false;
9588
9589         switch(vid.renderpath)
9590         {
9591         case RENDERPATH_GL20:
9592         case RENDERPATH_CGGL:
9593         case RENDERPATH_D3D9:
9594         case RENDERPATH_D3D10:
9595         case RENDERPATH_D3D11:
9596                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9597                 {
9598                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9599                         {
9600                                 // build GLSL gamma texture
9601 #define RAMPWIDTH 256
9602                                 unsigned short ramp[RAMPWIDTH * 3];
9603                                 unsigned char rampbgr[RAMPWIDTH][4];
9604                                 int i;
9605
9606                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9607
9608                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9609                                 for(i = 0; i < RAMPWIDTH; ++i)
9610                                 {
9611                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9612                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9613                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9614                                         rampbgr[i][3] = 0;
9615                                 }
9616                                 if (r_texture_gammaramps)
9617                                 {
9618                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9619                                 }
9620                                 else
9621                                 {
9622                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9623                                 }
9624                         }
9625                 }
9626                 else
9627                 {
9628                         // remove GLSL gamma texture
9629                 }
9630                 break;
9631         case RENDERPATH_GL13:
9632         case RENDERPATH_GL11:
9633                 break;
9634         }
9635 }
9636
9637 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9638 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9639 /*
9640 ================
9641 R_SelectScene
9642 ================
9643 */
9644 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9645         if( scenetype != r_currentscenetype ) {
9646                 // store the old scenetype
9647                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9648                 r_currentscenetype = scenetype;
9649                 // move in the new scene
9650                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9651         }
9652 }
9653
9654 /*
9655 ================
9656 R_GetScenePointer
9657 ================
9658 */
9659 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9660 {
9661         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9662         if( scenetype == r_currentscenetype ) {
9663                 return &r_refdef.scene;
9664         } else {
9665                 return &r_scenes_store[ scenetype ];
9666         }
9667 }
9668
9669 /*
9670 ================
9671 R_RenderView
9672 ================
9673 */
9674 void R_RenderView(void)
9675 {
9676         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9677         if (r_timereport_active)
9678                 R_TimeReport("start");
9679         r_textureframe++; // used only by R_GetCurrentTexture
9680         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9681
9682         if(R_CompileShader_CheckStaticParms())
9683                 R_GLSL_Restart_f();
9684
9685         if (!r_drawentities.integer)
9686                 r_refdef.scene.numentities = 0;
9687
9688         R_AnimCache_ClearCache();
9689         R_FrameData_NewFrame();
9690
9691         /* adjust for stereo display */
9692         if(R_Stereo_Active())
9693         {
9694                 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);
9695                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9696         }
9697
9698         if (r_refdef.view.isoverlay)
9699         {
9700                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9701                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9702                 R_TimeReport("depthclear");
9703
9704                 r_refdef.view.showdebug = false;
9705
9706                 r_waterstate.enabled = false;
9707                 r_waterstate.numwaterplanes = 0;
9708
9709                 R_RenderScene();
9710
9711                 r_refdef.view.matrix = originalmatrix;
9712
9713                 CHECKGLERROR
9714                 return;
9715         }
9716
9717         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9718         {
9719                 r_refdef.view.matrix = originalmatrix;
9720                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9721         }
9722
9723         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9724
9725         R_RenderView_UpdateViewVectors();
9726
9727         R_Shadow_UpdateWorldLightSelection();
9728
9729         R_Bloom_StartFrame();
9730         R_Water_StartFrame();
9731
9732         CHECKGLERROR
9733         if (r_timereport_active)
9734                 R_TimeReport("viewsetup");
9735
9736         R_ResetViewRendering3D();
9737
9738         if (r_refdef.view.clear || r_refdef.fogenabled)
9739         {
9740                 R_ClearScreen(r_refdef.fogenabled);
9741                 if (r_timereport_active)
9742                         R_TimeReport("viewclear");
9743         }
9744         r_refdef.view.clear = true;
9745
9746         // this produces a bloom texture to be used in R_BlendView() later
9747         if (r_hdr.integer && r_bloomstate.bloomwidth)
9748         {
9749                 R_HDR_RenderBloomTexture();
9750                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9751                 r_textureframe++; // used only by R_GetCurrentTexture
9752         }
9753
9754         r_refdef.view.showdebug = true;
9755
9756         R_View_Update();
9757         if (r_timereport_active)
9758                 R_TimeReport("visibility");
9759
9760         r_waterstate.numwaterplanes = 0;
9761         if (r_waterstate.enabled)
9762                 R_RenderWaterPlanes();
9763
9764         R_RenderScene();
9765         r_waterstate.numwaterplanes = 0;
9766
9767         R_BlendView();
9768         if (r_timereport_active)
9769                 R_TimeReport("blendview");
9770
9771         GL_Scissor(0, 0, vid.width, vid.height);
9772         GL_ScissorTest(false);
9773
9774         r_refdef.view.matrix = originalmatrix;
9775
9776         CHECKGLERROR
9777 }
9778
9779 void R_RenderWaterPlanes(void)
9780 {
9781         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9782         {
9783                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9784                 if (r_timereport_active)
9785                         R_TimeReport("waterworld");
9786         }
9787
9788         // don't let sound skip if going slow
9789         if (r_refdef.scene.extraupdate)
9790                 S_ExtraUpdate ();
9791
9792         R_DrawModelsAddWaterPlanes();
9793         if (r_timereport_active)
9794                 R_TimeReport("watermodels");
9795
9796         if (r_waterstate.numwaterplanes)
9797         {
9798                 R_Water_ProcessPlanes();
9799                 if (r_timereport_active)
9800                         R_TimeReport("waterscenes");
9801         }
9802 }
9803
9804 extern void R_DrawLightningBeams (void);
9805 extern void VM_CL_AddPolygonsToMeshQueue (void);
9806 extern void R_DrawPortals (void);
9807 extern cvar_t cl_locs_show;
9808 static void R_DrawLocs(void);
9809 static void R_DrawEntityBBoxes(void);
9810 static void R_DrawModelDecals(void);
9811 extern void R_DrawModelShadows(void);
9812 extern void R_DrawModelShadowMaps(void);
9813 extern cvar_t cl_decals_newsystem;
9814 extern qboolean r_shadow_usingdeferredprepass;
9815 void R_RenderScene(void)
9816 {
9817         qboolean shadowmapping = false;
9818
9819         if (r_timereport_active)
9820                 R_TimeReport("beginscene");
9821
9822         r_refdef.stats.renders++;
9823
9824         R_UpdateFogColor();
9825
9826         // don't let sound skip if going slow
9827         if (r_refdef.scene.extraupdate)
9828                 S_ExtraUpdate ();
9829
9830         R_MeshQueue_BeginScene();
9831
9832         R_SkyStartFrame();
9833
9834         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);
9835
9836         if (r_timereport_active)
9837                 R_TimeReport("skystartframe");
9838
9839         if (cl.csqc_vidvars.drawworld)
9840         {
9841                 // don't let sound skip if going slow
9842                 if (r_refdef.scene.extraupdate)
9843                         S_ExtraUpdate ();
9844
9845                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9846                 {
9847                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9848                         if (r_timereport_active)
9849                                 R_TimeReport("worldsky");
9850                 }
9851
9852                 if (R_DrawBrushModelsSky() && r_timereport_active)
9853                         R_TimeReport("bmodelsky");
9854
9855                 if (skyrendermasked && skyrenderlater)
9856                 {
9857                         // we have to force off the water clipping plane while rendering sky
9858                         R_SetupView(false);
9859                         R_Sky();
9860                         R_SetupView(true);
9861                         if (r_timereport_active)
9862                                 R_TimeReport("sky");
9863                 }
9864         }
9865
9866         R_AnimCache_CacheVisibleEntities();
9867         if (r_timereport_active)
9868                 R_TimeReport("animation");
9869
9870         R_Shadow_PrepareLights();
9871         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9872                 R_Shadow_PrepareModelShadows();
9873         if (r_timereport_active)
9874                 R_TimeReport("preparelights");
9875
9876         if (R_Shadow_ShadowMappingEnabled())
9877                 shadowmapping = true;
9878
9879         if (r_shadow_usingdeferredprepass)
9880                 R_Shadow_DrawPrepass();
9881
9882         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9883         {
9884                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9885                 if (r_timereport_active)
9886                         R_TimeReport("worlddepth");
9887         }
9888         if (r_depthfirst.integer >= 2)
9889         {
9890                 R_DrawModelsDepth();
9891                 if (r_timereport_active)
9892                         R_TimeReport("modeldepth");
9893         }
9894
9895         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9896         {
9897                 R_DrawModelShadowMaps();
9898                 R_ResetViewRendering3D();
9899                 // don't let sound skip if going slow
9900                 if (r_refdef.scene.extraupdate)
9901                         S_ExtraUpdate ();
9902         }
9903
9904         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9905         {
9906                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9907                 if (r_timereport_active)
9908                         R_TimeReport("world");
9909         }
9910
9911         // don't let sound skip if going slow
9912         if (r_refdef.scene.extraupdate)
9913                 S_ExtraUpdate ();
9914
9915         R_DrawModels();
9916         if (r_timereport_active)
9917                 R_TimeReport("models");
9918
9919         // don't let sound skip if going slow
9920         if (r_refdef.scene.extraupdate)
9921                 S_ExtraUpdate ();
9922
9923         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9924         {
9925                 R_DrawModelShadows();
9926                 R_ResetViewRendering3D();
9927                 // don't let sound skip if going slow
9928                 if (r_refdef.scene.extraupdate)
9929                         S_ExtraUpdate ();
9930         }
9931
9932         if (!r_shadow_usingdeferredprepass)
9933         {
9934                 R_Shadow_DrawLights();
9935                 if (r_timereport_active)
9936                         R_TimeReport("rtlights");
9937         }
9938
9939         // don't let sound skip if going slow
9940         if (r_refdef.scene.extraupdate)
9941                 S_ExtraUpdate ();
9942
9943         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9944         {
9945                 R_DrawModelShadows();
9946                 R_ResetViewRendering3D();
9947                 // don't let sound skip if going slow
9948                 if (r_refdef.scene.extraupdate)
9949                         S_ExtraUpdate ();
9950         }
9951
9952         if (cl.csqc_vidvars.drawworld)
9953         {
9954                 if (cl_decals_newsystem.integer)
9955                 {
9956                         R_DrawModelDecals();
9957                         if (r_timereport_active)
9958                                 R_TimeReport("modeldecals");
9959                 }
9960                 else
9961                 {
9962                         R_DrawDecals();
9963                         if (r_timereport_active)
9964                                 R_TimeReport("decals");
9965                 }
9966
9967                 R_DrawParticles();
9968                 if (r_timereport_active)
9969                         R_TimeReport("particles");
9970
9971                 R_DrawExplosions();
9972                 if (r_timereport_active)
9973                         R_TimeReport("explosions");
9974
9975                 R_DrawLightningBeams();
9976                 if (r_timereport_active)
9977                         R_TimeReport("lightning");
9978         }
9979
9980         VM_CL_AddPolygonsToMeshQueue();
9981
9982         if (r_refdef.view.showdebug)
9983         {
9984                 if (cl_locs_show.integer)
9985                 {
9986                         R_DrawLocs();
9987                         if (r_timereport_active)
9988                                 R_TimeReport("showlocs");
9989                 }
9990
9991                 if (r_drawportals.integer)
9992                 {
9993                         R_DrawPortals();
9994                         if (r_timereport_active)
9995                                 R_TimeReport("portals");
9996                 }
9997
9998                 if (r_showbboxes.value > 0)
9999                 {
10000                         R_DrawEntityBBoxes();
10001                         if (r_timereport_active)
10002                                 R_TimeReport("bboxes");
10003                 }
10004         }
10005
10006         R_MeshQueue_RenderTransparent();
10007         if (r_timereport_active)
10008                 R_TimeReport("drawtrans");
10009
10010         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))
10011         {
10012                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10013                 if (r_timereport_active)
10014                         R_TimeReport("worlddebug");
10015                 R_DrawModelsDebug();
10016                 if (r_timereport_active)
10017                         R_TimeReport("modeldebug");
10018         }
10019
10020         if (cl.csqc_vidvars.drawworld)
10021         {
10022                 R_Shadow_DrawCoronas();
10023                 if (r_timereport_active)
10024                         R_TimeReport("coronas");
10025         }
10026
10027 #if 0
10028         {
10029                 GL_DepthTest(false);
10030                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10031                 GL_Color(1, 1, 1, 1);
10032                 qglBegin(GL_POLYGON);
10033                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10034                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10035                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10036                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10037                 qglEnd();
10038                 qglBegin(GL_POLYGON);
10039                 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]);
10040                 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]);
10041                 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]);
10042                 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]);
10043                 qglEnd();
10044                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10045         }
10046 #endif
10047
10048         // don't let sound skip if going slow
10049         if (r_refdef.scene.extraupdate)
10050                 S_ExtraUpdate ();
10051
10052         R_ResetViewRendering2D();
10053 }
10054
10055 static const unsigned short bboxelements[36] =
10056 {
10057         5, 1, 3, 5, 3, 7,
10058         6, 2, 0, 6, 0, 4,
10059         7, 3, 2, 7, 2, 6,
10060         4, 0, 1, 4, 1, 5,
10061         4, 5, 7, 4, 7, 6,
10062         1, 0, 2, 1, 2, 3,
10063 };
10064
10065 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10066 {
10067         int i;
10068         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10069
10070         RSurf_ActiveWorldEntity();
10071
10072         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10073         GL_DepthMask(false);
10074         GL_DepthRange(0, 1);
10075         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10076 //      R_Mesh_ResetTextureState();
10077
10078         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10079         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10080         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10081         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10082         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10083         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10084         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10085         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10086         R_FillColors(color4f, 8, cr, cg, cb, ca);
10087         if (r_refdef.fogenabled)
10088         {
10089                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10090                 {
10091                         f1 = RSurf_FogVertex(v);
10092                         f2 = 1 - f1;
10093                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10094                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10095                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10096                 }
10097         }
10098         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10099         R_Mesh_ResetTextureState();
10100         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10101         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10102 }
10103
10104 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10105 {
10106         int i;
10107         float color[4];
10108         prvm_edict_t *edict;
10109         prvm_prog_t *prog_save = prog;
10110
10111         // this function draws bounding boxes of server entities
10112         if (!sv.active)
10113                 return;
10114
10115         GL_CullFace(GL_NONE);
10116         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10117
10118         prog = 0;
10119         SV_VM_Begin();
10120         for (i = 0;i < numsurfaces;i++)
10121         {
10122                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10123                 switch ((int)edict->fields.server->solid)
10124                 {
10125                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10126                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10127                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10128                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10129                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10130                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10131                 }
10132                 color[3] *= r_showbboxes.value;
10133                 color[3] = bound(0, color[3], 1);
10134                 GL_DepthTest(!r_showdisabledepthtest.integer);
10135                 GL_CullFace(r_refdef.view.cullface_front);
10136                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10137         }
10138         SV_VM_End();
10139         prog = prog_save;
10140 }
10141
10142 static void R_DrawEntityBBoxes(void)
10143 {
10144         int i;
10145         prvm_edict_t *edict;
10146         vec3_t center;
10147         prvm_prog_t *prog_save = prog;
10148
10149         // this function draws bounding boxes of server entities
10150         if (!sv.active)
10151                 return;
10152
10153         prog = 0;
10154         SV_VM_Begin();
10155         for (i = 0;i < prog->num_edicts;i++)
10156         {
10157                 edict = PRVM_EDICT_NUM(i);
10158                 if (edict->priv.server->free)
10159                         continue;
10160                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10161                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10162                         continue;
10163                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10164                         continue;
10165                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10166                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10167         }
10168         SV_VM_End();
10169         prog = prog_save;
10170 }
10171
10172 static const int nomodelelement3i[24] =
10173 {
10174         5, 2, 0,
10175         5, 1, 2,
10176         5, 0, 3,
10177         5, 3, 1,
10178         0, 2, 4,
10179         2, 1, 4,
10180         3, 0, 4,
10181         1, 3, 4
10182 };
10183
10184 static const unsigned short nomodelelement3s[24] =
10185 {
10186         5, 2, 0,
10187         5, 1, 2,
10188         5, 0, 3,
10189         5, 3, 1,
10190         0, 2, 4,
10191         2, 1, 4,
10192         3, 0, 4,
10193         1, 3, 4
10194 };
10195
10196 static const float nomodelvertex3f[6*3] =
10197 {
10198         -16,   0,   0,
10199          16,   0,   0,
10200           0, -16,   0,
10201           0,  16,   0,
10202           0,   0, -16,
10203           0,   0,  16
10204 };
10205
10206 static const float nomodelcolor4f[6*4] =
10207 {
10208         0.0f, 0.0f, 0.5f, 1.0f,
10209         0.0f, 0.0f, 0.5f, 1.0f,
10210         0.0f, 0.5f, 0.0f, 1.0f,
10211         0.0f, 0.5f, 0.0f, 1.0f,
10212         0.5f, 0.0f, 0.0f, 1.0f,
10213         0.5f, 0.0f, 0.0f, 1.0f
10214 };
10215
10216 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10217 {
10218         int i;
10219         float f1, f2, *c;
10220         float color4f[6*4];
10221
10222         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);
10223
10224         // this is only called once per entity so numsurfaces is always 1, and
10225         // surfacelist is always {0}, so this code does not handle batches
10226
10227         if (rsurface.ent_flags & RENDER_ADDITIVE)
10228         {
10229                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10230                 GL_DepthMask(false);
10231         }
10232         else if (rsurface.colormod[3] < 1)
10233         {
10234                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10235                 GL_DepthMask(false);
10236         }
10237         else
10238         {
10239                 GL_BlendFunc(GL_ONE, GL_ZERO);
10240                 GL_DepthMask(true);
10241         }
10242         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10243         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10244         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10245         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10246         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10247         for (i = 0, c = color4f;i < 6;i++, c += 4)
10248         {
10249                 c[0] *= rsurface.colormod[0];
10250                 c[1] *= rsurface.colormod[1];
10251                 c[2] *= rsurface.colormod[2];
10252                 c[3] *= rsurface.colormod[3];
10253         }
10254         if (r_refdef.fogenabled)
10255         {
10256                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10257                 {
10258                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10259                         f2 = 1 - f1;
10260                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10261                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10262                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10263                 }
10264         }
10265 //      R_Mesh_ResetTextureState();
10266         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10267         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10268         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10269 }
10270
10271 void R_DrawNoModel(entity_render_t *ent)
10272 {
10273         vec3_t org;
10274         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10275         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10276                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10277         else
10278                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10279 }
10280
10281 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10282 {
10283         vec3_t right1, right2, diff, normal;
10284
10285         VectorSubtract (org2, org1, normal);
10286
10287         // calculate 'right' vector for start
10288         VectorSubtract (r_refdef.view.origin, org1, diff);
10289         CrossProduct (normal, diff, right1);
10290         VectorNormalize (right1);
10291
10292         // calculate 'right' vector for end
10293         VectorSubtract (r_refdef.view.origin, org2, diff);
10294         CrossProduct (normal, diff, right2);
10295         VectorNormalize (right2);
10296
10297         vert[ 0] = org1[0] + width * right1[0];
10298         vert[ 1] = org1[1] + width * right1[1];
10299         vert[ 2] = org1[2] + width * right1[2];
10300         vert[ 3] = org1[0] - width * right1[0];
10301         vert[ 4] = org1[1] - width * right1[1];
10302         vert[ 5] = org1[2] - width * right1[2];
10303         vert[ 6] = org2[0] - width * right2[0];
10304         vert[ 7] = org2[1] - width * right2[1];
10305         vert[ 8] = org2[2] - width * right2[2];
10306         vert[ 9] = org2[0] + width * right2[0];
10307         vert[10] = org2[1] + width * right2[1];
10308         vert[11] = org2[2] + width * right2[2];
10309 }
10310
10311 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)
10312 {
10313         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10314         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10315         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10316         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10317         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10318         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10319         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10320         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10321         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10322         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10323         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10324         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10325 }
10326
10327 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10328 {
10329         int i;
10330         float *vertex3f;
10331         float v[3];
10332         VectorSet(v, x, y, z);
10333         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10334                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10335                         break;
10336         if (i == mesh->numvertices)
10337         {
10338                 if (mesh->numvertices < mesh->maxvertices)
10339                 {
10340                         VectorCopy(v, vertex3f);
10341                         mesh->numvertices++;
10342                 }
10343                 return mesh->numvertices;
10344         }
10345         else
10346                 return i;
10347 }
10348
10349 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10350 {
10351         int i;
10352         int *e, element[3];
10353         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10354         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10355         e = mesh->element3i + mesh->numtriangles * 3;
10356         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10357         {
10358                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10359                 if (mesh->numtriangles < mesh->maxtriangles)
10360                 {
10361                         *e++ = element[0];
10362                         *e++ = element[1];
10363                         *e++ = element[2];
10364                         mesh->numtriangles++;
10365                 }
10366                 element[1] = element[2];
10367         }
10368 }
10369
10370 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10371 {
10372         int i;
10373         int *e, element[3];
10374         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10375         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10376         e = mesh->element3i + mesh->numtriangles * 3;
10377         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10378         {
10379                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10380                 if (mesh->numtriangles < mesh->maxtriangles)
10381                 {
10382                         *e++ = element[0];
10383                         *e++ = element[1];
10384                         *e++ = element[2];
10385                         mesh->numtriangles++;
10386                 }
10387                 element[1] = element[2];
10388         }
10389 }
10390
10391 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10392 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10393 {
10394         int planenum, planenum2;
10395         int w;
10396         int tempnumpoints;
10397         mplane_t *plane, *plane2;
10398         double maxdist;
10399         double temppoints[2][256*3];
10400         // figure out how large a bounding box we need to properly compute this brush
10401         maxdist = 0;
10402         for (w = 0;w < numplanes;w++)
10403                 maxdist = max(maxdist, fabs(planes[w].dist));
10404         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10405         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10406         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10407         {
10408                 w = 0;
10409                 tempnumpoints = 4;
10410                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10411                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10412                 {
10413                         if (planenum2 == planenum)
10414                                 continue;
10415                         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);
10416                         w = !w;
10417                 }
10418                 if (tempnumpoints < 3)
10419                         continue;
10420                 // generate elements forming a triangle fan for this polygon
10421                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10422         }
10423 }
10424
10425 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)
10426 {
10427         texturelayer_t *layer;
10428         layer = t->currentlayers + t->currentnumlayers++;
10429         layer->type = type;
10430         layer->depthmask = depthmask;
10431         layer->blendfunc1 = blendfunc1;
10432         layer->blendfunc2 = blendfunc2;
10433         layer->texture = texture;
10434         layer->texmatrix = *matrix;
10435         layer->color[0] = r;
10436         layer->color[1] = g;
10437         layer->color[2] = b;
10438         layer->color[3] = a;
10439 }
10440
10441 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10442 {
10443         if(parms[0] == 0 && parms[1] == 0)
10444                 return false;
10445         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10446                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10447                         return false;
10448         return true;
10449 }
10450
10451 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10452 {
10453         double index, f;
10454         index = parms[2] + r_refdef.scene.time * parms[3];
10455         index -= floor(index);
10456         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10457         {
10458         default:
10459         case Q3WAVEFUNC_NONE:
10460         case Q3WAVEFUNC_NOISE:
10461         case Q3WAVEFUNC_COUNT:
10462                 f = 0;
10463                 break;
10464         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10465         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10466         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10467         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10468         case Q3WAVEFUNC_TRIANGLE:
10469                 index *= 4;
10470                 f = index - floor(index);
10471                 if (index < 1)
10472                         f = f;
10473                 else if (index < 2)
10474                         f = 1 - f;
10475                 else if (index < 3)
10476                         f = -f;
10477                 else
10478                         f = -(1 - f);
10479                 break;
10480         }
10481         f = parms[0] + parms[1] * f;
10482         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10483                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10484         return (float) f;
10485 }
10486
10487 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10488 {
10489         int w, h, idx;
10490         float f;
10491         float tcmat[12];
10492         matrix4x4_t matrix, temp;
10493         switch(tcmod->tcmod)
10494         {
10495                 case Q3TCMOD_COUNT:
10496                 case Q3TCMOD_NONE:
10497                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10498                                 matrix = r_waterscrollmatrix;
10499                         else
10500                                 matrix = identitymatrix;
10501                         break;
10502                 case Q3TCMOD_ENTITYTRANSLATE:
10503                         // this is used in Q3 to allow the gamecode to control texcoord
10504                         // scrolling on the entity, which is not supported in darkplaces yet.
10505                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10506                         break;
10507                 case Q3TCMOD_ROTATE:
10508                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10509                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10510                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10511                         break;
10512                 case Q3TCMOD_SCALE:
10513                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10514                         break;
10515                 case Q3TCMOD_SCROLL:
10516                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10517                         break;
10518                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10519                         w = (int) tcmod->parms[0];
10520                         h = (int) tcmod->parms[1];
10521                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10522                         f = f - floor(f);
10523                         idx = (int) floor(f * w * h);
10524                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10525                         break;
10526                 case Q3TCMOD_STRETCH:
10527                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10528                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10529                         break;
10530                 case Q3TCMOD_TRANSFORM:
10531                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10532                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10533                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10534                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10535                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10536                         break;
10537                 case Q3TCMOD_TURBULENT:
10538                         // this is handled in the RSurf_PrepareVertices function
10539                         matrix = identitymatrix;
10540                         break;
10541         }
10542         temp = *texmatrix;
10543         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10544 }
10545
10546 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10547 {
10548         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10549         char name[MAX_QPATH];
10550         skinframe_t *skinframe;
10551         unsigned char pixels[296*194];
10552         strlcpy(cache->name, skinname, sizeof(cache->name));
10553         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10554         if (developer_loading.integer)
10555                 Con_Printf("loading %s\n", name);
10556         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10557         if (!skinframe || !skinframe->base)
10558         {
10559                 unsigned char *f;
10560                 fs_offset_t filesize;
10561                 skinframe = NULL;
10562                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10563                 if (f)
10564                 {
10565                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10566                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10567                         Mem_Free(f);
10568                 }
10569         }
10570         cache->skinframe = skinframe;
10571 }
10572
10573 texture_t *R_GetCurrentTexture(texture_t *t)
10574 {
10575         int i;
10576         const entity_render_t *ent = rsurface.entity;
10577         dp_model_t *model = ent->model;
10578         q3shaderinfo_layer_tcmod_t *tcmod;
10579
10580         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10581                 return t->currentframe;
10582         t->update_lastrenderframe = r_textureframe;
10583         t->update_lastrenderentity = (void *)ent;
10584
10585         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10586                 t->camera_entity = ent->entitynumber;
10587         else
10588                 t->camera_entity = 0;
10589
10590         // switch to an alternate material if this is a q1bsp animated material
10591         {
10592                 texture_t *texture = t;
10593                 int s = rsurface.ent_skinnum;
10594                 if ((unsigned int)s >= (unsigned int)model->numskins)
10595                         s = 0;
10596                 if (model->skinscenes)
10597                 {
10598                         if (model->skinscenes[s].framecount > 1)
10599                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10600                         else
10601                                 s = model->skinscenes[s].firstframe;
10602                 }
10603                 if (s > 0)
10604                         t = t + s * model->num_surfaces;
10605                 if (t->animated)
10606                 {
10607                         // use an alternate animation if the entity's frame is not 0,
10608                         // and only if the texture has an alternate animation
10609                         if (rsurface.ent_alttextures && t->anim_total[1])
10610                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10611                         else
10612                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10613                 }
10614                 texture->currentframe = t;
10615         }
10616
10617         // update currentskinframe to be a qw skin or animation frame
10618         if (rsurface.ent_qwskin >= 0)
10619         {
10620                 i = rsurface.ent_qwskin;
10621                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10622                 {
10623                         r_qwskincache_size = cl.maxclients;
10624                         if (r_qwskincache)
10625                                 Mem_Free(r_qwskincache);
10626                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10627                 }
10628                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10629                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10630                 t->currentskinframe = r_qwskincache[i].skinframe;
10631                 if (t->currentskinframe == NULL)
10632                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10633         }
10634         else if (t->numskinframes >= 2)
10635                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10636         if (t->backgroundnumskinframes >= 2)
10637                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10638
10639         t->currentmaterialflags = t->basematerialflags;
10640         t->currentalpha = rsurface.colormod[3];
10641         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10642                 t->currentalpha *= r_wateralpha.value;
10643         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10644                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10645         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10646                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10647         if (!(rsurface.ent_flags & RENDER_LIGHT))
10648                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10649         else if (FAKELIGHT_ENABLED)
10650         {
10651                         // no modellight if using fakelight for the map
10652         }
10653         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10654         {
10655                 // pick a model lighting mode
10656                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10657                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10658                 else
10659                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10660         }
10661         if (rsurface.ent_flags & RENDER_ADDITIVE)
10662                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10663         else if (t->currentalpha < 1)
10664                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10665         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10666                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10667         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10668                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10669         if (t->backgroundnumskinframes)
10670                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10671         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10672         {
10673                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10674                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10675         }
10676         else
10677                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10678         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10679                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10680
10681         // there is no tcmod
10682         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10683         {
10684                 t->currenttexmatrix = r_waterscrollmatrix;
10685                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10686         }
10687         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10688         {
10689                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10690                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10691         }
10692
10693         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10694                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10695         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10696                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10697
10698         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10699         if (t->currentskinframe->qpixels)
10700                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10701         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10702         if (!t->basetexture)
10703                 t->basetexture = r_texture_notexture;
10704         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10705         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10706         t->nmaptexture = t->currentskinframe->nmap;
10707         if (!t->nmaptexture)
10708                 t->nmaptexture = r_texture_blanknormalmap;
10709         t->glosstexture = r_texture_black;
10710         t->glowtexture = t->currentskinframe->glow;
10711         t->fogtexture = t->currentskinframe->fog;
10712         t->reflectmasktexture = t->currentskinframe->reflect;
10713         if (t->backgroundnumskinframes)
10714         {
10715                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10716                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10717                 t->backgroundglosstexture = r_texture_black;
10718                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10719                 if (!t->backgroundnmaptexture)
10720                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10721         }
10722         else
10723         {
10724                 t->backgroundbasetexture = r_texture_white;
10725                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10726                 t->backgroundglosstexture = r_texture_black;
10727                 t->backgroundglowtexture = NULL;
10728         }
10729         t->specularpower = r_shadow_glossexponent.value;
10730         // TODO: store reference values for these in the texture?
10731         t->specularscale = 0;
10732         if (r_shadow_gloss.integer > 0)
10733         {
10734                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10735                 {
10736                         if (r_shadow_glossintensity.value > 0)
10737                         {
10738                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10739                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10740                                 t->specularscale = r_shadow_glossintensity.value;
10741                         }
10742                 }
10743                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10744                 {
10745                         t->glosstexture = r_texture_white;
10746                         t->backgroundglosstexture = r_texture_white;
10747                         t->specularscale = r_shadow_gloss2intensity.value;
10748                         t->specularpower = r_shadow_gloss2exponent.value;
10749                 }
10750         }
10751         t->specularscale *= t->specularscalemod;
10752         t->specularpower *= t->specularpowermod;
10753
10754         // lightmaps mode looks bad with dlights using actual texturing, so turn
10755         // off the colormap and glossmap, but leave the normalmap on as it still
10756         // accurately represents the shading involved
10757         if (gl_lightmaps.integer)
10758         {
10759                 t->basetexture = r_texture_grey128;
10760                 t->pantstexture = r_texture_black;
10761                 t->shirttexture = r_texture_black;
10762                 t->nmaptexture = r_texture_blanknormalmap;
10763                 t->glosstexture = r_texture_black;
10764                 t->glowtexture = NULL;
10765                 t->fogtexture = NULL;
10766                 t->reflectmasktexture = NULL;
10767                 t->backgroundbasetexture = NULL;
10768                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10769                 t->backgroundglosstexture = r_texture_black;
10770                 t->backgroundglowtexture = NULL;
10771                 t->specularscale = 0;
10772                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10773         }
10774
10775         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10776         VectorClear(t->dlightcolor);
10777         t->currentnumlayers = 0;
10778         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10779         {
10780                 int blendfunc1, blendfunc2;
10781                 qboolean depthmask;
10782                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10783                 {
10784                         blendfunc1 = GL_SRC_ALPHA;
10785                         blendfunc2 = GL_ONE;
10786                 }
10787                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10788                 {
10789                         blendfunc1 = GL_SRC_ALPHA;
10790                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10791                 }
10792                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10793                 {
10794                         blendfunc1 = t->customblendfunc[0];
10795                         blendfunc2 = t->customblendfunc[1];
10796                 }
10797                 else
10798                 {
10799                         blendfunc1 = GL_ONE;
10800                         blendfunc2 = GL_ZERO;
10801                 }
10802                 // don't colormod evilblend textures
10803                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10804                         VectorSet(t->lightmapcolor, 1, 1, 1);
10805                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10806                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10807                 {
10808                         // fullbright is not affected by r_refdef.lightmapintensity
10809                         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]);
10810                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10811                                 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]);
10812                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10813                                 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]);
10814                 }
10815                 else
10816                 {
10817                         vec3_t ambientcolor;
10818                         float colorscale;
10819                         // set the color tint used for lights affecting this surface
10820                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10821                         colorscale = 2;
10822                         // q3bsp has no lightmap updates, so the lightstylevalue that
10823                         // would normally be baked into the lightmap must be
10824                         // applied to the color
10825                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10826                         if (model->type == mod_brushq3)
10827                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10828                         colorscale *= r_refdef.lightmapintensity;
10829                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10830                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10831                         // basic lit geometry
10832                         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]);
10833                         // add pants/shirt if needed
10834                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10835                                 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]);
10836                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10837                                 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]);
10838                         // now add ambient passes if needed
10839                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10840                         {
10841                                 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]);
10842                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10843                                         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]);
10844                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10845                                         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]);
10846                         }
10847                 }
10848                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10849                         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]);
10850                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10851                 {
10852                         // if this is opaque use alpha blend which will darken the earlier
10853                         // passes cheaply.
10854                         //
10855                         // if this is an alpha blended material, all the earlier passes
10856                         // were darkened by fog already, so we only need to add the fog
10857                         // color ontop through the fog mask texture
10858                         //
10859                         // if this is an additive blended material, all the earlier passes
10860                         // were darkened by fog already, and we should not add fog color
10861                         // (because the background was not darkened, there is no fog color
10862                         // that was lost behind it).
10863                         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]);
10864                 }
10865         }
10866
10867         return t->currentframe;
10868 }
10869
10870 rsurfacestate_t rsurface;
10871
10872 void RSurf_ActiveWorldEntity(void)
10873 {
10874         dp_model_t *model = r_refdef.scene.worldmodel;
10875         //if (rsurface.entity == r_refdef.scene.worldentity)
10876         //      return;
10877         rsurface.entity = r_refdef.scene.worldentity;
10878         rsurface.skeleton = NULL;
10879         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10880         rsurface.ent_skinnum = 0;
10881         rsurface.ent_qwskin = -1;
10882         rsurface.ent_shadertime = 0;
10883         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10884         rsurface.matrix = identitymatrix;
10885         rsurface.inversematrix = identitymatrix;
10886         rsurface.matrixscale = 1;
10887         rsurface.inversematrixscale = 1;
10888         R_EntityMatrix(&identitymatrix);
10889         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10890         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10891         rsurface.fograngerecip = r_refdef.fograngerecip;
10892         rsurface.fogheightfade = r_refdef.fogheightfade;
10893         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10894         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10895         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10896         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10897         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10898         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10899         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10900         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10901         rsurface.colormod[3] = 1;
10902         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);
10903         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10904         rsurface.frameblend[0].lerp = 1;
10905         rsurface.ent_alttextures = false;
10906         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10907         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10908         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10909         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10910         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10911         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10912         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10913         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10914         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10915         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10916         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10917         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10918         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10919         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10920         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10921         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10922         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10923         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10924         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10925         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10926         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10927         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10928         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10929         rsurface.modelelement3i = model->surfmesh.data_element3i;
10930         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10931         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10932         rsurface.modelelement3s = model->surfmesh.data_element3s;
10933         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10934         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10935         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10936         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10937         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10938         rsurface.modelsurfaces = model->data_surfaces;
10939         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10940         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10941         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10942         rsurface.modelgeneratedvertex = false;
10943         rsurface.batchgeneratedvertex = false;
10944         rsurface.batchfirstvertex = 0;
10945         rsurface.batchnumvertices = 0;
10946         rsurface.batchfirsttriangle = 0;
10947         rsurface.batchnumtriangles = 0;
10948         rsurface.batchvertex3f  = NULL;
10949         rsurface.batchvertex3f_vertexbuffer = NULL;
10950         rsurface.batchvertex3f_bufferoffset = 0;
10951         rsurface.batchsvector3f = NULL;
10952         rsurface.batchsvector3f_vertexbuffer = NULL;
10953         rsurface.batchsvector3f_bufferoffset = 0;
10954         rsurface.batchtvector3f = NULL;
10955         rsurface.batchtvector3f_vertexbuffer = NULL;
10956         rsurface.batchtvector3f_bufferoffset = 0;
10957         rsurface.batchnormal3f  = NULL;
10958         rsurface.batchnormal3f_vertexbuffer = NULL;
10959         rsurface.batchnormal3f_bufferoffset = 0;
10960         rsurface.batchlightmapcolor4f = NULL;
10961         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10962         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10963         rsurface.batchtexcoordtexture2f = NULL;
10964         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10965         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10966         rsurface.batchtexcoordlightmap2f = NULL;
10967         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10968         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10969         rsurface.batchvertexmesh = NULL;
10970         rsurface.batchvertexmeshbuffer = NULL;
10971         rsurface.batchvertex3fbuffer = NULL;
10972         rsurface.batchelement3i = NULL;
10973         rsurface.batchelement3i_indexbuffer = NULL;
10974         rsurface.batchelement3i_bufferoffset = 0;
10975         rsurface.batchelement3s = NULL;
10976         rsurface.batchelement3s_indexbuffer = NULL;
10977         rsurface.batchelement3s_bufferoffset = 0;
10978         rsurface.passcolor4f = NULL;
10979         rsurface.passcolor4f_vertexbuffer = NULL;
10980         rsurface.passcolor4f_bufferoffset = 0;
10981 }
10982
10983 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10984 {
10985         dp_model_t *model = ent->model;
10986         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10987         //      return;
10988         rsurface.entity = (entity_render_t *)ent;
10989         rsurface.skeleton = ent->skeleton;
10990         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10991         rsurface.ent_skinnum = ent->skinnum;
10992         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;
10993         rsurface.ent_shadertime = ent->shadertime;
10994         rsurface.ent_flags = ent->flags;
10995         rsurface.matrix = ent->matrix;
10996         rsurface.inversematrix = ent->inversematrix;
10997         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10998         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10999         R_EntityMatrix(&rsurface.matrix);
11000         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11001         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11002         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11003         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11004         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11005         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11006         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11007         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11008         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11009         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11010         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11011         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11012         rsurface.colormod[3] = ent->alpha;
11013         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11014         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11015         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11016         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11017         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11018         if (ent->model->brush.submodel && !prepass)
11019         {
11020                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11021                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11022         }
11023         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11024         {
11025                 if (ent->animcache_vertex3f)
11026                 {
11027                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11028                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11029                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11030                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11031                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11032                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11033                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11034                 }
11035                 else if (wanttangents)
11036                 {
11037                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11038                         rsurface.modelsvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11039                         rsurface.modeltvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11040                         rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11041                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11042                         rsurface.modelvertexmesh = NULL;
11043                         rsurface.modelvertexmeshbuffer = NULL;
11044                         rsurface.modelvertex3fbuffer = NULL;
11045                 }
11046                 else if (wantnormals)
11047                 {
11048                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11049                         rsurface.modelsvector3f = NULL;
11050                         rsurface.modeltvector3f = NULL;
11051                         rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11052                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11053                         rsurface.modelvertexmesh = NULL;
11054                         rsurface.modelvertexmeshbuffer = NULL;
11055                         rsurface.modelvertex3fbuffer = NULL;
11056                 }
11057                 else
11058                 {
11059                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11060                         rsurface.modelsvector3f = NULL;
11061                         rsurface.modeltvector3f = NULL;
11062                         rsurface.modelnormal3f = NULL;
11063                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11064                         rsurface.modelvertexmesh = NULL;
11065                         rsurface.modelvertexmeshbuffer = NULL;
11066                         rsurface.modelvertex3fbuffer = NULL;
11067                 }
11068                 rsurface.modelvertex3f_vertexbuffer = 0;
11069                 rsurface.modelvertex3f_bufferoffset = 0;
11070                 rsurface.modelsvector3f_vertexbuffer = 0;
11071                 rsurface.modelsvector3f_bufferoffset = 0;
11072                 rsurface.modeltvector3f_vertexbuffer = 0;
11073                 rsurface.modeltvector3f_bufferoffset = 0;
11074                 rsurface.modelnormal3f_vertexbuffer = 0;
11075                 rsurface.modelnormal3f_bufferoffset = 0;
11076                 rsurface.modelgeneratedvertex = true;
11077         }
11078         else
11079         {
11080                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11081                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11082                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11083                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11084                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11085                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11086                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11087                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11088                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11089                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11090                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11091                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11092                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11093                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11094                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11095                 rsurface.modelgeneratedvertex = false;
11096         }
11097         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11098         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11099         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11100         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11101         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11102         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11103         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11104         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11105         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11106         rsurface.modelelement3i = model->surfmesh.data_element3i;
11107         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11108         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11109         rsurface.modelelement3s = model->surfmesh.data_element3s;
11110         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11111         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11112         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11113         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11114         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11115         rsurface.modelsurfaces = model->data_surfaces;
11116         rsurface.batchgeneratedvertex = false;
11117         rsurface.batchfirstvertex = 0;
11118         rsurface.batchnumvertices = 0;
11119         rsurface.batchfirsttriangle = 0;
11120         rsurface.batchnumtriangles = 0;
11121         rsurface.batchvertex3f  = NULL;
11122         rsurface.batchvertex3f_vertexbuffer = NULL;
11123         rsurface.batchvertex3f_bufferoffset = 0;
11124         rsurface.batchsvector3f = NULL;
11125         rsurface.batchsvector3f_vertexbuffer = NULL;
11126         rsurface.batchsvector3f_bufferoffset = 0;
11127         rsurface.batchtvector3f = NULL;
11128         rsurface.batchtvector3f_vertexbuffer = NULL;
11129         rsurface.batchtvector3f_bufferoffset = 0;
11130         rsurface.batchnormal3f  = NULL;
11131         rsurface.batchnormal3f_vertexbuffer = NULL;
11132         rsurface.batchnormal3f_bufferoffset = 0;
11133         rsurface.batchlightmapcolor4f = NULL;
11134         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11135         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11136         rsurface.batchtexcoordtexture2f = NULL;
11137         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11138         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11139         rsurface.batchtexcoordlightmap2f = NULL;
11140         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11141         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11142         rsurface.batchvertexmesh = NULL;
11143         rsurface.batchvertexmeshbuffer = NULL;
11144         rsurface.batchvertex3fbuffer = NULL;
11145         rsurface.batchelement3i = NULL;
11146         rsurface.batchelement3i_indexbuffer = NULL;
11147         rsurface.batchelement3i_bufferoffset = 0;
11148         rsurface.batchelement3s = NULL;
11149         rsurface.batchelement3s_indexbuffer = NULL;
11150         rsurface.batchelement3s_bufferoffset = 0;
11151         rsurface.passcolor4f = NULL;
11152         rsurface.passcolor4f_vertexbuffer = NULL;
11153         rsurface.passcolor4f_bufferoffset = 0;
11154 }
11155
11156 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)
11157 {
11158         rsurface.entity = r_refdef.scene.worldentity;
11159         rsurface.skeleton = NULL;
11160         rsurface.ent_skinnum = 0;
11161         rsurface.ent_qwskin = -1;
11162         rsurface.ent_shadertime = shadertime;
11163         rsurface.ent_flags = entflags;
11164         rsurface.modelnumvertices = numvertices;
11165         rsurface.modelnumtriangles = numtriangles;
11166         rsurface.matrix = *matrix;
11167         rsurface.inversematrix = *inversematrix;
11168         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11169         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11170         R_EntityMatrix(&rsurface.matrix);
11171         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11172         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11173         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11174         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11175         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11176         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11177         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11178         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11179         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11180         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11181         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11182         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11183         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);
11184         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11185         rsurface.frameblend[0].lerp = 1;
11186         rsurface.ent_alttextures = false;
11187         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11188         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11189         if (wanttangents)
11190         {
11191                 rsurface.modelvertex3f = (float *)vertex3f;
11192                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11193                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11194                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11195         }
11196         else if (wantnormals)
11197         {
11198                 rsurface.modelvertex3f = (float *)vertex3f;
11199                 rsurface.modelsvector3f = NULL;
11200                 rsurface.modeltvector3f = NULL;
11201                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11202         }
11203         else
11204         {
11205                 rsurface.modelvertex3f = (float *)vertex3f;
11206                 rsurface.modelsvector3f = NULL;
11207                 rsurface.modeltvector3f = NULL;
11208                 rsurface.modelnormal3f = NULL;
11209         }
11210         rsurface.modelvertexmesh = NULL;
11211         rsurface.modelvertexmeshbuffer = NULL;
11212         rsurface.modelvertex3fbuffer = NULL;
11213         rsurface.modelvertex3f_vertexbuffer = 0;
11214         rsurface.modelvertex3f_bufferoffset = 0;
11215         rsurface.modelsvector3f_vertexbuffer = 0;
11216         rsurface.modelsvector3f_bufferoffset = 0;
11217         rsurface.modeltvector3f_vertexbuffer = 0;
11218         rsurface.modeltvector3f_bufferoffset = 0;
11219         rsurface.modelnormal3f_vertexbuffer = 0;
11220         rsurface.modelnormal3f_bufferoffset = 0;
11221         rsurface.modelgeneratedvertex = true;
11222         rsurface.modellightmapcolor4f  = (float *)color4f;
11223         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11224         rsurface.modellightmapcolor4f_bufferoffset = 0;
11225         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11226         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11227         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11228         rsurface.modeltexcoordlightmap2f  = NULL;
11229         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11230         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11231         rsurface.modelelement3i = (int *)element3i;
11232         rsurface.modelelement3i_indexbuffer = NULL;
11233         rsurface.modelelement3i_bufferoffset = 0;
11234         rsurface.modelelement3s = (unsigned short *)element3s;
11235         rsurface.modelelement3s_indexbuffer = NULL;
11236         rsurface.modelelement3s_bufferoffset = 0;
11237         rsurface.modellightmapoffsets = NULL;
11238         rsurface.modelsurfaces = NULL;
11239         rsurface.batchgeneratedvertex = false;
11240         rsurface.batchfirstvertex = 0;
11241         rsurface.batchnumvertices = 0;
11242         rsurface.batchfirsttriangle = 0;
11243         rsurface.batchnumtriangles = 0;
11244         rsurface.batchvertex3f  = NULL;
11245         rsurface.batchvertex3f_vertexbuffer = NULL;
11246         rsurface.batchvertex3f_bufferoffset = 0;
11247         rsurface.batchsvector3f = NULL;
11248         rsurface.batchsvector3f_vertexbuffer = NULL;
11249         rsurface.batchsvector3f_bufferoffset = 0;
11250         rsurface.batchtvector3f = NULL;
11251         rsurface.batchtvector3f_vertexbuffer = NULL;
11252         rsurface.batchtvector3f_bufferoffset = 0;
11253         rsurface.batchnormal3f  = NULL;
11254         rsurface.batchnormal3f_vertexbuffer = NULL;
11255         rsurface.batchnormal3f_bufferoffset = 0;
11256         rsurface.batchlightmapcolor4f = NULL;
11257         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11258         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11259         rsurface.batchtexcoordtexture2f = NULL;
11260         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11261         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11262         rsurface.batchtexcoordlightmap2f = NULL;
11263         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11264         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11265         rsurface.batchvertexmesh = NULL;
11266         rsurface.batchvertexmeshbuffer = NULL;
11267         rsurface.batchvertex3fbuffer = NULL;
11268         rsurface.batchelement3i = NULL;
11269         rsurface.batchelement3i_indexbuffer = NULL;
11270         rsurface.batchelement3i_bufferoffset = 0;
11271         rsurface.batchelement3s = NULL;
11272         rsurface.batchelement3s_indexbuffer = NULL;
11273         rsurface.batchelement3s_bufferoffset = 0;
11274         rsurface.passcolor4f = NULL;
11275         rsurface.passcolor4f_vertexbuffer = NULL;
11276         rsurface.passcolor4f_bufferoffset = 0;
11277
11278         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11279         {
11280                 if ((wantnormals || wanttangents) && !normal3f)
11281                 {
11282                         rsurface.modelnormal3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11283                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11284                 }
11285                 if (wanttangents && !svector3f)
11286                 {
11287                         rsurface.modelsvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11288                         rsurface.modeltvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11289                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11290                 }
11291         }
11292 }
11293
11294 float RSurf_FogPoint(const float *v)
11295 {
11296         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11297         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11298         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11299         float FogHeightFade = r_refdef.fogheightfade;
11300         float fogfrac;
11301         unsigned int fogmasktableindex;
11302         if (r_refdef.fogplaneviewabove)
11303                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11304         else
11305                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11306         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11307         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11308 }
11309
11310 float RSurf_FogVertex(const float *v)
11311 {
11312         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11313         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11314         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11315         float FogHeightFade = rsurface.fogheightfade;
11316         float fogfrac;
11317         unsigned int fogmasktableindex;
11318         if (r_refdef.fogplaneviewabove)
11319                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11320         else
11321                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11322         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11323         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11324 }
11325
11326 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11327 {
11328         int i;
11329         for (i = 0;i < numelements;i++)
11330                 outelement3i[i] = inelement3i[i] + adjust;
11331 }
11332
11333 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11334 extern cvar_t gl_vbo;
11335 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11336 {
11337         int deformindex;
11338         int firsttriangle;
11339         int numtriangles;
11340         int firstvertex;
11341         int endvertex;
11342         int numvertices;
11343         int surfacefirsttriangle;
11344         int surfacenumtriangles;
11345         int surfacefirstvertex;
11346         int surfaceendvertex;
11347         int surfacenumvertices;
11348         int batchnumvertices;
11349         int batchnumtriangles;
11350         int needsupdate;
11351         int i, j;
11352         qboolean gaps;
11353         qboolean dynamicvertex;
11354         float amplitude;
11355         float animpos;
11356         float scale;
11357         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11358         float waveparms[4];
11359         q3shaderinfo_deform_t *deform;
11360         const msurface_t *surface, *firstsurface;
11361         r_vertexmesh_t *vertexmesh;
11362         if (!texturenumsurfaces)
11363                 return;
11364         // find vertex range of this surface batch
11365         gaps = false;
11366         firstsurface = texturesurfacelist[0];
11367         firsttriangle = firstsurface->num_firsttriangle;
11368         batchnumvertices = 0;
11369         batchnumtriangles = 0;
11370         firstvertex = endvertex = firstsurface->num_firstvertex;
11371         for (i = 0;i < texturenumsurfaces;i++)
11372         {
11373                 surface = texturesurfacelist[i];
11374                 if (surface != firstsurface + i)
11375                         gaps = true;
11376                 surfacefirstvertex = surface->num_firstvertex;
11377                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11378                 surfacenumvertices = surface->num_vertices;
11379                 surfacenumtriangles = surface->num_triangles;
11380                 if (firstvertex > surfacefirstvertex)
11381                         firstvertex = surfacefirstvertex;
11382                 if (endvertex < surfaceendvertex)
11383                         endvertex = surfaceendvertex;
11384                 batchnumvertices += surfacenumvertices;
11385                 batchnumtriangles += surfacenumtriangles;
11386         }
11387
11388         // we now know the vertex range used, and if there are any gaps in it
11389         rsurface.batchfirstvertex = firstvertex;
11390         rsurface.batchnumvertices = endvertex - firstvertex;
11391         rsurface.batchfirsttriangle = firsttriangle;
11392         rsurface.batchnumtriangles = batchnumtriangles;
11393
11394         // this variable holds flags for which properties have been updated that
11395         // may require regenerating vertexmesh array...
11396         needsupdate = 0;
11397
11398         // check if any dynamic vertex processing must occur
11399         dynamicvertex = false;
11400
11401         // if there is a chance of animated vertex colors, it's a dynamic batch
11402         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11403         {
11404                 dynamicvertex = true;
11405                 batchneed |= BATCHNEED_NOGAPS;
11406                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11407         }
11408
11409         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11410         {
11411                 switch (deform->deform)
11412                 {
11413                 default:
11414                 case Q3DEFORM_PROJECTIONSHADOW:
11415                 case Q3DEFORM_TEXT0:
11416                 case Q3DEFORM_TEXT1:
11417                 case Q3DEFORM_TEXT2:
11418                 case Q3DEFORM_TEXT3:
11419                 case Q3DEFORM_TEXT4:
11420                 case Q3DEFORM_TEXT5:
11421                 case Q3DEFORM_TEXT6:
11422                 case Q3DEFORM_TEXT7:
11423                 case Q3DEFORM_NONE:
11424                         break;
11425                 case Q3DEFORM_AUTOSPRITE:
11426                         dynamicvertex = true;
11427                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11428                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11429                         break;
11430                 case Q3DEFORM_AUTOSPRITE2:
11431                         dynamicvertex = true;
11432                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11433                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11434                         break;
11435                 case Q3DEFORM_NORMAL:
11436                         dynamicvertex = true;
11437                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11438                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11439                         break;
11440                 case Q3DEFORM_WAVE:
11441                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11442                                 break; // if wavefunc is a nop, ignore this transform
11443                         dynamicvertex = true;
11444                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11445                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11446                         break;
11447                 case Q3DEFORM_BULGE:
11448                         dynamicvertex = true;
11449                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11450                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11451                         break;
11452                 case Q3DEFORM_MOVE:
11453                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11454                                 break; // if wavefunc is a nop, ignore this transform
11455                         dynamicvertex = true;
11456                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11457                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11458                         break;
11459                 }
11460         }
11461         switch(rsurface.texture->tcgen.tcgen)
11462         {
11463         default:
11464         case Q3TCGEN_TEXTURE:
11465                 break;
11466         case Q3TCGEN_LIGHTMAP:
11467                 dynamicvertex = true;
11468                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11469                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11470                 break;
11471         case Q3TCGEN_VECTOR:
11472                 dynamicvertex = true;
11473                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11474                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11475                 break;
11476         case Q3TCGEN_ENVIRONMENT:
11477                 dynamicvertex = true;
11478                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11479                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11480                 break;
11481         }
11482         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11483         {
11484                 dynamicvertex = true;
11485                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11486                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11487         }
11488
11489         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11490         {
11491                 dynamicvertex = true;
11492                 batchneed |= BATCHNEED_NOGAPS;
11493                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11494         }
11495
11496         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11497         {
11498                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11499                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11500                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11501                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11502                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11503                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11504                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11505         }
11506
11507         // when the model data has no vertex buffer (dynamic mesh), we need to
11508         // eliminate gaps
11509         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11510                 batchneed |= BATCHNEED_NOGAPS;
11511
11512         // if needsupdate, we have to do a dynamic vertex batch for sure
11513         if (needsupdate & batchneed)
11514                 dynamicvertex = true;
11515
11516         // see if we need to build vertexmesh from arrays
11517         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11518                 dynamicvertex = true;
11519
11520         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11521         // also some drivers strongly dislike firstvertex
11522         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11523                 dynamicvertex = true;
11524
11525         rsurface.batchvertex3f = rsurface.modelvertex3f;
11526         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11527         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11528         rsurface.batchsvector3f = rsurface.modelsvector3f;
11529         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11530         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11531         rsurface.batchtvector3f = rsurface.modeltvector3f;
11532         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11533         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11534         rsurface.batchnormal3f = rsurface.modelnormal3f;
11535         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11536         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11537         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11538         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11539         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11540         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11541         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11542         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11543         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11544         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11545         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11546         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11547         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11548         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11549         rsurface.batchelement3i = rsurface.modelelement3i;
11550         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11551         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11552         rsurface.batchelement3s = rsurface.modelelement3s;
11553         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11554         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11555
11556         // if any dynamic vertex processing has to occur in software, we copy the
11557         // entire surface list together before processing to rebase the vertices
11558         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11559         //
11560         // if any gaps exist and we do not have a static vertex buffer, we have to
11561         // copy the surface list together to avoid wasting upload bandwidth on the
11562         // vertices in the gaps.
11563         //
11564         // if gaps exist and we have a static vertex buffer, we still have to
11565         // combine the index buffer ranges into one dynamic index buffer.
11566         //
11567         // in all cases we end up with data that can be drawn in one call.
11568
11569         if (!dynamicvertex)
11570         {
11571                 // static vertex data, just set pointers...
11572                 rsurface.batchgeneratedvertex = false;
11573                 // if there are gaps, we want to build a combined index buffer,
11574                 // otherwise use the original static buffer with an appropriate offset
11575                 if (gaps)
11576                 {
11577                         // build a new triangle elements array for this batch
11578                         rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11579                         rsurface.batchfirsttriangle = 0;
11580                         numtriangles = 0;
11581                         for (i = 0;i < texturenumsurfaces;i++)
11582                         {
11583                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11584                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11585                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11586                                 numtriangles += surfacenumtriangles;
11587                         }
11588                         rsurface.batchelement3i_indexbuffer = NULL;
11589                         rsurface.batchelement3i_bufferoffset = 0;
11590                         rsurface.batchelement3s = NULL;
11591                         rsurface.batchelement3s_indexbuffer = NULL;
11592                         rsurface.batchelement3s_bufferoffset = 0;
11593                         if (endvertex <= 65536)
11594                         {
11595                                 // make a 16bit (unsigned short) index array if possible
11596                                 rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11597                                 for (i = 0;i < numtriangles*3;i++)
11598                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11599                         }
11600                 }
11601                 return;
11602         }
11603
11604         // something needs software processing, do it for real...
11605         // we only directly handle separate array data in this case and then
11606         // generate interleaved data if needed...
11607         rsurface.batchgeneratedvertex = true;
11608
11609         // now copy the vertex data into a combined array and make an index array
11610         // (this is what Quake3 does all the time)
11611         //if (gaps || rsurface.batchfirstvertex)
11612         {
11613                 rsurface.batchvertex3fbuffer = NULL;
11614                 rsurface.batchvertexmesh = NULL;
11615                 rsurface.batchvertexmeshbuffer = NULL;
11616                 rsurface.batchvertex3f = NULL;
11617                 rsurface.batchvertex3f_vertexbuffer = NULL;
11618                 rsurface.batchvertex3f_bufferoffset = 0;
11619                 rsurface.batchsvector3f = NULL;
11620                 rsurface.batchsvector3f_vertexbuffer = NULL;
11621                 rsurface.batchsvector3f_bufferoffset = 0;
11622                 rsurface.batchtvector3f = NULL;
11623                 rsurface.batchtvector3f_vertexbuffer = NULL;
11624                 rsurface.batchtvector3f_bufferoffset = 0;
11625                 rsurface.batchnormal3f = NULL;
11626                 rsurface.batchnormal3f_vertexbuffer = NULL;
11627                 rsurface.batchnormal3f_bufferoffset = 0;
11628                 rsurface.batchlightmapcolor4f = NULL;
11629                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11630                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11631                 rsurface.batchtexcoordtexture2f = NULL;
11632                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11633                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11634                 rsurface.batchtexcoordlightmap2f = NULL;
11635                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11636                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11637                 rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11638                 rsurface.batchelement3i_indexbuffer = NULL;
11639                 rsurface.batchelement3i_bufferoffset = 0;
11640                 rsurface.batchelement3s = NULL;
11641                 rsurface.batchelement3s_indexbuffer = NULL;
11642                 rsurface.batchelement3s_bufferoffset = 0;
11643                 // we'll only be setting up certain arrays as needed
11644                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11645                         rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11646                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11647                         rsurface.batchvertex3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11648                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11649                         rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11650                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11651                 {
11652                         rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11653                         rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11654                 }
11655                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11656                         rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11657                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11658                         rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11659                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11660                         rsurface.batchtexcoordlightmap2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11661                 numvertices = 0;
11662                 numtriangles = 0;
11663                 for (i = 0;i < texturenumsurfaces;i++)
11664                 {
11665                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11666                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11667                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11668                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11669                         // copy only the data requested
11670                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11671                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11672                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11673                         {
11674                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11675                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11676                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11677                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11678                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11679                                 {
11680                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11681                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11682                                 }
11683                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11684                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11685                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11686                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11687                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11688                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11689                         }
11690                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11691                         numvertices += surfacenumvertices;
11692                         numtriangles += surfacenumtriangles;
11693                 }
11694
11695                 // generate a 16bit index array as well if possible
11696                 // (in general, dynamic batches fit)
11697                 if (numvertices <= 65536)
11698                 {
11699                         rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11700                         for (i = 0;i < numtriangles*3;i++)
11701                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11702                 }
11703
11704                 // since we've copied everything, the batch now starts at 0
11705                 rsurface.batchfirstvertex = 0;
11706                 rsurface.batchnumvertices = batchnumvertices;
11707                 rsurface.batchfirsttriangle = 0;
11708                 rsurface.batchnumtriangles = batchnumtriangles;
11709         }
11710
11711         // q1bsp surfaces rendered in vertex color mode have to have colors
11712         // calculated based on lightstyles
11713         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11714         {
11715                 // generate color arrays for the surfaces in this list
11716                 int c[4];
11717                 int scale;
11718                 int size3;
11719                 const int *offsets;
11720                 const unsigned char *lm;
11721                 rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11722                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11723                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11724                 numvertices = 0;
11725                 for (i = 0;i < texturenumsurfaces;i++)
11726                 {
11727                         surface = texturesurfacelist[i];
11728                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11729                         surfacenumvertices = surface->num_vertices;
11730                         if (surface->lightmapinfo->samples)
11731                         {
11732                                 for (j = 0;j < surfacenumvertices;j++)
11733                                 {
11734                                         lm = surface->lightmapinfo->samples + offsets[j];
11735                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11736                                         VectorScale(lm, scale, c);
11737                                         if (surface->lightmapinfo->styles[1] != 255)
11738                                         {
11739                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11740                                                 lm += size3;
11741                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11742                                                 VectorMA(c, scale, lm, c);
11743                                                 if (surface->lightmapinfo->styles[2] != 255)
11744                                                 {
11745                                                         lm += size3;
11746                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11747                                                         VectorMA(c, scale, lm, c);
11748                                                         if (surface->lightmapinfo->styles[3] != 255)
11749                                                         {
11750                                                                 lm += size3;
11751                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11752                                                                 VectorMA(c, scale, lm, c);
11753                                                         }
11754                                                 }
11755                                         }
11756                                         c[0] >>= 15;
11757                                         c[1] >>= 15;
11758                                         c[2] >>= 15;
11759                                         Vector4Set(rsurface.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);
11760                                         numvertices++;
11761                                 }
11762                         }
11763                         else
11764                         {
11765                                 for (j = 0;j < surfacenumvertices;j++)
11766                                 {
11767                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11768                                         numvertices++;
11769                                 }
11770                         }
11771                 }
11772         }
11773
11774         // if vertices are deformed (sprite flares and things in maps, possibly
11775         // water waves, bulges and other deformations), modify the copied vertices
11776         // in place
11777         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11778         {
11779                 switch (deform->deform)
11780                 {
11781                 default:
11782                 case Q3DEFORM_PROJECTIONSHADOW:
11783                 case Q3DEFORM_TEXT0:
11784                 case Q3DEFORM_TEXT1:
11785                 case Q3DEFORM_TEXT2:
11786                 case Q3DEFORM_TEXT3:
11787                 case Q3DEFORM_TEXT4:
11788                 case Q3DEFORM_TEXT5:
11789                 case Q3DEFORM_TEXT6:
11790                 case Q3DEFORM_TEXT7:
11791                 case Q3DEFORM_NONE:
11792                         break;
11793                 case Q3DEFORM_AUTOSPRITE:
11794                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11795                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11796                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11797                         VectorNormalize(newforward);
11798                         VectorNormalize(newright);
11799                         VectorNormalize(newup);
11800 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11801 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11802 //                      rsurface.batchvertex3f_bufferoffset = 0;
11803 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11804 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11805 //                      rsurface.batchsvector3f_bufferoffset = 0;
11806 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11807 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11808 //                      rsurface.batchtvector3f_bufferoffset = 0;
11809 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11810 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11811 //                      rsurface.batchnormal3f_bufferoffset = 0;
11812                         // a single autosprite surface can contain multiple sprites...
11813                         for (j = 0;j < batchnumvertices - 3;j += 4)
11814                         {
11815                                 VectorClear(center);
11816                                 for (i = 0;i < 4;i++)
11817                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11818                                 VectorScale(center, 0.25f, center);
11819                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11820                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11821                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11822                                 for (i = 0;i < 4;i++)
11823                                 {
11824                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11825                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11826                                 }
11827                         }
11828                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11829                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11830                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11831                         break;
11832                 case Q3DEFORM_AUTOSPRITE2:
11833                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11834                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11835                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11836                         VectorNormalize(newforward);
11837                         VectorNormalize(newright);
11838                         VectorNormalize(newup);
11839 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11840 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11841 //                      rsurface.batchvertex3f_bufferoffset = 0;
11842                         {
11843                                 const float *v1, *v2;
11844                                 vec3_t start, end;
11845                                 float f, l;
11846                                 struct
11847                                 {
11848                                         float length2;
11849                                         const float *v1;
11850                                         const float *v2;
11851                                 }
11852                                 shortest[2];
11853                                 memset(shortest, 0, sizeof(shortest));
11854                                 // a single autosprite surface can contain multiple sprites...
11855                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11856                                 {
11857                                         VectorClear(center);
11858                                         for (i = 0;i < 4;i++)
11859                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11860                                         VectorScale(center, 0.25f, center);
11861                                         // find the two shortest edges, then use them to define the
11862                                         // axis vectors for rotating around the central axis
11863                                         for (i = 0;i < 6;i++)
11864                                         {
11865                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11866                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11867                                                 l = VectorDistance2(v1, v2);
11868                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11869                                                 if (v1[2] != v2[2])
11870                                                         l += (1.0f / 1024.0f);
11871                                                 if (shortest[0].length2 > l || i == 0)
11872                                                 {
11873                                                         shortest[1] = shortest[0];
11874                                                         shortest[0].length2 = l;
11875                                                         shortest[0].v1 = v1;
11876                                                         shortest[0].v2 = v2;
11877                                                 }
11878                                                 else if (shortest[1].length2 > l || i == 1)
11879                                                 {
11880                                                         shortest[1].length2 = l;
11881                                                         shortest[1].v1 = v1;
11882                                                         shortest[1].v2 = v2;
11883                                                 }
11884                                         }
11885                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11886                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11887                                         // this calculates the right vector from the shortest edge
11888                                         // and the up vector from the edge midpoints
11889                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11890                                         VectorNormalize(right);
11891                                         VectorSubtract(end, start, up);
11892                                         VectorNormalize(up);
11893                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11894                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11895                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11896                                         VectorNegate(forward, forward);
11897                                         VectorReflect(forward, 0, up, forward);
11898                                         VectorNormalize(forward);
11899                                         CrossProduct(up, forward, newright);
11900                                         VectorNormalize(newright);
11901                                         // rotate the quad around the up axis vector, this is made
11902                                         // especially easy by the fact we know the quad is flat,
11903                                         // so we only have to subtract the center position and
11904                                         // measure distance along the right vector, and then
11905                                         // multiply that by the newright vector and add back the
11906                                         // center position
11907                                         // we also need to subtract the old position to undo the
11908                                         // displacement from the center, which we do with a
11909                                         // DotProduct, the subtraction/addition of center is also
11910                                         // optimized into DotProducts here
11911                                         l = DotProduct(right, center);
11912                                         for (i = 0;i < 4;i++)
11913                                         {
11914                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11915                                                 f = DotProduct(right, v1) - l;
11916                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11917                                         }
11918                                 }
11919                         }
11920                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11921                         {
11922 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11923 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11924 //                              rsurface.batchnormal3f_bufferoffset = 0;
11925                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11926                         }
11927                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11928                         {
11929 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11930 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11931 //                              rsurface.batchsvector3f_bufferoffset = 0;
11932 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11933 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11934 //                              rsurface.batchtvector3f_bufferoffset = 0;
11935                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11936                         }
11937                         break;
11938                 case Q3DEFORM_NORMAL:
11939                         // deform the normals to make reflections wavey
11940                         rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11941                         rsurface.batchnormal3f_vertexbuffer = NULL;
11942                         rsurface.batchnormal3f_bufferoffset = 0;
11943                         for (j = 0;j < batchnumvertices;j++)
11944                         {
11945                                 float vertex[3];
11946                                 float *normal = rsurface.batchnormal3f + 3*j;
11947                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11948                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11949                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11950                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11951                                 VectorNormalize(normal);
11952                         }
11953                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11954                         {
11955 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11956 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11957 //                              rsurface.batchsvector3f_bufferoffset = 0;
11958 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11959 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11960 //                              rsurface.batchtvector3f_bufferoffset = 0;
11961                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11962                         }
11963                         break;
11964                 case Q3DEFORM_WAVE:
11965                         // deform vertex array to make wavey water and flags and such
11966                         waveparms[0] = deform->waveparms[0];
11967                         waveparms[1] = deform->waveparms[1];
11968                         waveparms[2] = deform->waveparms[2];
11969                         waveparms[3] = deform->waveparms[3];
11970                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11971                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11972                         // this is how a divisor of vertex influence on deformation
11973                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11974                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11975 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11976 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11977 //                      rsurface.batchvertex3f_bufferoffset = 0;
11978 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11979 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11980 //                      rsurface.batchnormal3f_bufferoffset = 0;
11981                         for (j = 0;j < batchnumvertices;j++)
11982                         {
11983                                 // if the wavefunc depends on time, evaluate it per-vertex
11984                                 if (waveparms[3])
11985                                 {
11986                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11987                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11988                                 }
11989                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11990                         }
11991                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11992                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11993                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11994                         {
11995 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11996 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11997 //                              rsurface.batchsvector3f_bufferoffset = 0;
11998 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11999 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12000 //                              rsurface.batchtvector3f_bufferoffset = 0;
12001                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12002                         }
12003                         break;
12004                 case Q3DEFORM_BULGE:
12005                         // deform vertex array to make the surface have moving bulges
12006 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12007 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12008 //                      rsurface.batchvertex3f_bufferoffset = 0;
12009 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12010 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12011 //                      rsurface.batchnormal3f_bufferoffset = 0;
12012                         for (j = 0;j < batchnumvertices;j++)
12013                         {
12014                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12015                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12016                         }
12017                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12018                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12019                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12020                         {
12021 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12022 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12023 //                              rsurface.batchsvector3f_bufferoffset = 0;
12024 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12025 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12026 //                              rsurface.batchtvector3f_bufferoffset = 0;
12027                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12028                         }
12029                         break;
12030                 case Q3DEFORM_MOVE:
12031                         // deform vertex array
12032                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12033                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12034                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12035                         VectorScale(deform->parms, scale, waveparms);
12036 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12037 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12038 //                      rsurface.batchvertex3f_bufferoffset = 0;
12039                         for (j = 0;j < batchnumvertices;j++)
12040                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12041                         break;
12042                 }
12043         }
12044
12045         // generate texcoords based on the chosen texcoord source
12046         switch(rsurface.texture->tcgen.tcgen)
12047         {
12048         default:
12049         case Q3TCGEN_TEXTURE:
12050                 break;
12051         case Q3TCGEN_LIGHTMAP:
12052 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12053 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12054 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12055                 if (rsurface.batchtexcoordlightmap2f)
12056                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12057                 break;
12058         case Q3TCGEN_VECTOR:
12059 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12060 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12061 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12062                 for (j = 0;j < batchnumvertices;j++)
12063                 {
12064                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12065                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12066                 }
12067                 break;
12068         case Q3TCGEN_ENVIRONMENT:
12069                 // make environment reflections using a spheremap
12070 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12071 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12072 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12073                 for (j = 0;j < batchnumvertices;j++)
12074                 {
12075                         // identical to Q3A's method, but executed in worldspace so
12076                         // carried models can be shiny too
12077
12078                         float viewer[3], d, reflected[3], worldreflected[3];
12079
12080                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12081                         // VectorNormalize(viewer);
12082
12083                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12084
12085                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12086                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12087                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12088                         // note: this is proportinal to viewer, so we can normalize later
12089
12090                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12091                         VectorNormalize(worldreflected);
12092
12093                         // note: this sphere map only uses world x and z!
12094                         // so positive and negative y will LOOK THE SAME.
12095                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12096                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12097                 }
12098                 break;
12099         }
12100         // the only tcmod that needs software vertex processing is turbulent, so
12101         // check for it here and apply the changes if needed
12102         // and we only support that as the first one
12103         // (handling a mixture of turbulent and other tcmods would be problematic
12104         //  without punting it entirely to a software path)
12105         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12106         {
12107                 amplitude = rsurface.texture->tcmods[0].parms[1];
12108                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12109 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12110 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12111 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12112                 for (j = 0;j < batchnumvertices;j++)
12113                 {
12114                         rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12115                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12116                 }
12117         }
12118
12119         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12120         {
12121                 // convert the modified arrays to vertex structs
12122 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12123 //              rsurface.batchvertexmeshbuffer = NULL;
12124                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12125                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12126                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12127                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12128                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12129                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12130                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12131                 {
12132                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12133                         {
12134                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12135                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12136                         }
12137                 }
12138                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12139                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12140                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12141                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12142                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12143                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12144                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12145                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12146                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12147         }
12148 }
12149
12150 void RSurf_DrawBatch(void)
12151 {
12152         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12153         // through the pipeline, killing it earlier in the pipeline would have
12154         // per-surface overhead rather than per-batch overhead, so it's best to
12155         // reject it here, before it hits glDraw.
12156         if (rsurface.batchnumtriangles == 0)
12157                 return;
12158 #if 0
12159         // batch debugging code
12160         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12161         {
12162                 int i;
12163                 int j;
12164                 int c;
12165                 const int *e;
12166                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12167                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12168                 {
12169                         c = e[i];
12170                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12171                         {
12172                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12173                                 {
12174                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12175                                                 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);
12176                                         break;
12177                                 }
12178                         }
12179                 }
12180         }
12181 #endif
12182         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);
12183 }
12184
12185 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12186 {
12187         // pick the closest matching water plane
12188         int planeindex, vertexindex, bestplaneindex = -1;
12189         float d, bestd;
12190         vec3_t vert;
12191         const float *v;
12192         r_waterstate_waterplane_t *p;
12193         qboolean prepared = false;
12194         bestd = 0;
12195         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12196         {
12197                 if(p->camera_entity != rsurface.texture->camera_entity)
12198                         continue;
12199                 d = 0;
12200                 if(!prepared)
12201                 {
12202                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12203                         prepared = true;
12204                         if(rsurface.batchnumvertices == 0)
12205                                 break;
12206                 }
12207                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12208                 {
12209                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12210                         d += fabs(PlaneDiff(vert, &p->plane));
12211                 }
12212                 if (bestd > d || bestplaneindex < 0)
12213                 {
12214                         bestd = d;
12215                         bestplaneindex = planeindex;
12216                 }
12217         }
12218         return bestplaneindex;
12219         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12220         // this situation though, as it might be better to render single larger
12221         // batches with useless stuff (backface culled for example) than to
12222         // render multiple smaller batches
12223 }
12224
12225 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12226 {
12227         int i;
12228         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12229         rsurface.passcolor4f_vertexbuffer = 0;
12230         rsurface.passcolor4f_bufferoffset = 0;
12231         for (i = 0;i < rsurface.batchnumvertices;i++)
12232                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12233 }
12234
12235 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12236 {
12237         int i;
12238         float f;
12239         const float *v;
12240         const float *c;
12241         float *c2;
12242         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12243         rsurface.passcolor4f_vertexbuffer = 0;
12244         rsurface.passcolor4f_bufferoffset = 0;
12245         if (rsurface.passcolor4f)
12246         {
12247                 // generate color arrays
12248                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12249                 {
12250                         f = RSurf_FogVertex(v);
12251                         c2[0] = c[0] * f;
12252                         c2[1] = c[1] * f;
12253                         c2[2] = c[2] * f;
12254                         c2[3] = c[3];
12255                 }
12256         }
12257         else
12258         {
12259                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12260                 {
12261                         f = RSurf_FogVertex(v);
12262                         c2[0] = f;
12263                         c2[1] = f;
12264                         c2[2] = f;
12265                         c2[3] = 1;
12266                 }
12267         }
12268 }
12269
12270 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12271 {
12272         int i;
12273         float f;
12274         const float *v;
12275         const float *c;
12276         float *c2;
12277         if (!rsurface.passcolor4f)
12278                 return;
12279         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12280         rsurface.passcolor4f_vertexbuffer = 0;
12281         rsurface.passcolor4f_bufferoffset = 0;
12282         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12283         {
12284                 f = RSurf_FogVertex(v);
12285                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12286                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12287                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12288                 c2[3] = c[3];
12289         }
12290 }
12291
12292 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12293 {
12294         int i;
12295         const float *c;
12296         float *c2;
12297         if (!rsurface.passcolor4f)
12298                 return;
12299         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12300         rsurface.passcolor4f_vertexbuffer = 0;
12301         rsurface.passcolor4f_bufferoffset = 0;
12302         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12303         {
12304                 c2[0] = c[0] * r;
12305                 c2[1] = c[1] * g;
12306                 c2[2] = c[2] * b;
12307                 c2[3] = c[3] * a;
12308         }
12309 }
12310
12311 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12312 {
12313         int i;
12314         const float *c;
12315         float *c2;
12316         if (!rsurface.passcolor4f)
12317                 return;
12318         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12319         rsurface.passcolor4f_vertexbuffer = 0;
12320         rsurface.passcolor4f_bufferoffset = 0;
12321         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12322         {
12323                 c2[0] = c[0] + r_refdef.scene.ambient;
12324                 c2[1] = c[1] + r_refdef.scene.ambient;
12325                 c2[2] = c[2] + r_refdef.scene.ambient;
12326                 c2[3] = c[3];
12327         }
12328 }
12329
12330 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12331 {
12332         // TODO: optimize
12333         rsurface.passcolor4f = NULL;
12334         rsurface.passcolor4f_vertexbuffer = 0;
12335         rsurface.passcolor4f_bufferoffset = 0;
12336         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12337         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12338         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12339         GL_Color(r, g, b, a);
12340         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12341         RSurf_DrawBatch();
12342 }
12343
12344 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12345 {
12346         // TODO: optimize applyfog && applycolor case
12347         // just apply fog if necessary, and tint the fog color array if necessary
12348         rsurface.passcolor4f = NULL;
12349         rsurface.passcolor4f_vertexbuffer = 0;
12350         rsurface.passcolor4f_bufferoffset = 0;
12351         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12352         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12353         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12354         GL_Color(r, g, b, a);
12355         RSurf_DrawBatch();
12356 }
12357
12358 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12359 {
12360         // TODO: optimize
12361         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12362         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12363         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12364         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12365         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12366         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12367         GL_Color(r, g, b, a);
12368         RSurf_DrawBatch();
12369 }
12370
12371 static void RSurf_DrawBatch_GL11_ClampColor(void)
12372 {
12373         int i;
12374         const float *c1;
12375         float *c2;
12376         if (!rsurface.passcolor4f)
12377                 return;
12378         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12379         {
12380                 c2[0] = bound(0.0f, c1[0], 1.0f);
12381                 c2[1] = bound(0.0f, c1[1], 1.0f);
12382                 c2[2] = bound(0.0f, c1[2], 1.0f);
12383                 c2[3] = bound(0.0f, c1[3], 1.0f);
12384         }
12385 }
12386
12387 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12388 {
12389         int i;
12390         float f;
12391         const float *v;
12392         const float *n;
12393         float *c;
12394         //vec3_t eyedir;
12395
12396         // fake shading
12397         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12398         rsurface.passcolor4f_vertexbuffer = 0;
12399         rsurface.passcolor4f_bufferoffset = 0;
12400         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12401         {
12402                 f = -DotProduct(r_refdef.view.forward, n);
12403                 f = max(0, f);
12404                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12405                 f *= r_refdef.lightmapintensity;
12406                 Vector4Set(c, f, f, f, 1);
12407         }
12408 }
12409
12410 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12411 {
12412         RSurf_DrawBatch_GL11_ApplyFakeLight();
12413         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12414         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12415         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12416         GL_Color(r, g, b, a);
12417         RSurf_DrawBatch();
12418 }
12419
12420 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12421 {
12422         int i;
12423         float f;
12424         float alpha;
12425         const float *v;
12426         const float *n;
12427         float *c;
12428         vec3_t ambientcolor;
12429         vec3_t diffusecolor;
12430         vec3_t lightdir;
12431         // TODO: optimize
12432         // model lighting
12433         VectorCopy(rsurface.modellight_lightdir, lightdir);
12434         f = 0.5f * r_refdef.lightmapintensity;
12435         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12436         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12437         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12438         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12439         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12440         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12441         alpha = *a;
12442         if (VectorLength2(diffusecolor) > 0)
12443         {
12444                 // q3-style directional shading
12445                 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12446                 rsurface.passcolor4f_vertexbuffer = 0;
12447                 rsurface.passcolor4f_bufferoffset = 0;
12448                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12449                 {
12450                         if ((f = DotProduct(n, lightdir)) > 0)
12451                                 VectorMA(ambientcolor, f, diffusecolor, c);
12452                         else
12453                                 VectorCopy(ambientcolor, c);
12454                         c[3] = alpha;
12455                 }
12456                 *r = 1;
12457                 *g = 1;
12458                 *b = 1;
12459                 *a = 1;
12460                 *applycolor = false;
12461         }
12462         else
12463         {
12464                 *r = ambientcolor[0];
12465                 *g = ambientcolor[1];
12466                 *b = ambientcolor[2];
12467                 rsurface.passcolor4f = NULL;
12468                 rsurface.passcolor4f_vertexbuffer = 0;
12469                 rsurface.passcolor4f_bufferoffset = 0;
12470         }
12471 }
12472
12473 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12474 {
12475         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12476         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12477         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12478         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12479         GL_Color(r, g, b, a);
12480         RSurf_DrawBatch();
12481 }
12482
12483 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12484 {
12485         int i;
12486         float f;
12487         const float *v;
12488         float *c;
12489         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12490         {
12491                 f = 1 - RSurf_FogVertex(v);
12492                 c[0] = r;
12493                 c[1] = g;
12494                 c[2] = b;
12495                 c[3] = f * a;
12496         }
12497 }
12498
12499 void RSurf_SetupDepthAndCulling(void)
12500 {
12501         // submodels are biased to avoid z-fighting with world surfaces that they
12502         // may be exactly overlapping (avoids z-fighting artifacts on certain
12503         // doors and things in Quake maps)
12504         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12505         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12506         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12507         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12508 }
12509
12510 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12511 {
12512         // transparent sky would be ridiculous
12513         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12514                 return;
12515         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12516         skyrenderlater = true;
12517         RSurf_SetupDepthAndCulling();
12518         GL_DepthMask(true);
12519         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12520         // skymasking on them, and Quake3 never did sky masking (unlike
12521         // software Quake and software Quake2), so disable the sky masking
12522         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12523         // and skymasking also looks very bad when noclipping outside the
12524         // level, so don't use it then either.
12525         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12526         {
12527                 R_Mesh_ResetTextureState();
12528                 if (skyrendermasked)
12529                 {
12530                         R_SetupShader_DepthOrShadow();
12531                         // depth-only (masking)
12532                         GL_ColorMask(0,0,0,0);
12533                         // just to make sure that braindead drivers don't draw
12534                         // anything despite that colormask...
12535                         GL_BlendFunc(GL_ZERO, GL_ONE);
12536                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12537                         if (rsurface.batchvertex3fbuffer)
12538                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12539                         else
12540                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12541                 }
12542                 else
12543                 {
12544                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12545                         // fog sky
12546                         GL_BlendFunc(GL_ONE, GL_ZERO);
12547                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12548                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12549                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12550                 }
12551                 RSurf_DrawBatch();
12552                 if (skyrendermasked)
12553                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12554         }
12555         R_Mesh_ResetTextureState();
12556         GL_Color(1, 1, 1, 1);
12557 }
12558
12559 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12560 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12561 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12562 {
12563         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12564                 return;
12565         if (prepass)
12566         {
12567                 // render screenspace normalmap to texture
12568                 GL_DepthMask(true);
12569                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12570                 RSurf_DrawBatch();
12571                 return;
12572         }
12573
12574         // bind lightmap texture
12575
12576         // water/refraction/reflection/camera surfaces have to be handled specially
12577         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12578         {
12579                 int start, end, startplaneindex;
12580                 for (start = 0;start < texturenumsurfaces;start = end)
12581                 {
12582                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12583                         if(startplaneindex < 0)
12584                         {
12585                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12586                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12587                                 end = start + 1;
12588                                 continue;
12589                         }
12590                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12591                                 ;
12592                         // now that we have a batch using the same planeindex, render it
12593                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12594                         {
12595                                 // render water or distortion background
12596                                 GL_DepthMask(true);
12597                                 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));
12598                                 RSurf_DrawBatch();
12599                                 // blend surface on top
12600                                 GL_DepthMask(false);
12601                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12602                                 RSurf_DrawBatch();
12603                         }
12604                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12605                         {
12606                                 // render surface with reflection texture as input
12607                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12608                                 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));
12609                                 RSurf_DrawBatch();
12610                         }
12611                 }
12612                 return;
12613         }
12614
12615         // render surface batch normally
12616         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12617         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12618         RSurf_DrawBatch();
12619 }
12620
12621 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12622 {
12623         // OpenGL 1.3 path - anything not completely ancient
12624         qboolean applycolor;
12625         qboolean applyfog;
12626         int layerindex;
12627         const texturelayer_t *layer;
12628         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);
12629         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12630
12631         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12632         {
12633                 vec4_t layercolor;
12634                 int layertexrgbscale;
12635                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12636                 {
12637                         if (layerindex == 0)
12638                                 GL_AlphaTest(true);
12639                         else
12640                         {
12641                                 GL_AlphaTest(false);
12642                                 GL_DepthFunc(GL_EQUAL);
12643                         }
12644                 }
12645                 GL_DepthMask(layer->depthmask && writedepth);
12646                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12647                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12648                 {
12649                         layertexrgbscale = 4;
12650                         VectorScale(layer->color, 0.25f, layercolor);
12651                 }
12652                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12653                 {
12654                         layertexrgbscale = 2;
12655                         VectorScale(layer->color, 0.5f, layercolor);
12656                 }
12657                 else
12658                 {
12659                         layertexrgbscale = 1;
12660                         VectorScale(layer->color, 1.0f, layercolor);
12661                 }
12662                 layercolor[3] = layer->color[3];
12663                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12664                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12665                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12666                 switch (layer->type)
12667                 {
12668                 case TEXTURELAYERTYPE_LITTEXTURE:
12669                         // single-pass lightmapped texture with 2x rgbscale
12670                         R_Mesh_TexBind(0, r_texture_white);
12671                         R_Mesh_TexMatrix(0, NULL);
12672                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12673                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12674                         R_Mesh_TexBind(1, layer->texture);
12675                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12676                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12677                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12678                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12679                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12680                         else if (FAKELIGHT_ENABLED)
12681                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12682                         else if (rsurface.uselightmaptexture)
12683                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12684                         else
12685                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12686                         break;
12687                 case TEXTURELAYERTYPE_TEXTURE:
12688                         // singletexture unlit texture with transparency support
12689                         R_Mesh_TexBind(0, layer->texture);
12690                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12691                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12692                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12693                         R_Mesh_TexBind(1, 0);
12694                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12695                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12696                         break;
12697                 case TEXTURELAYERTYPE_FOG:
12698                         // singletexture fogging
12699                         if (layer->texture)
12700                         {
12701                                 R_Mesh_TexBind(0, layer->texture);
12702                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12703                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12704                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12705                         }
12706                         else
12707                         {
12708                                 R_Mesh_TexBind(0, 0);
12709                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12710                         }
12711                         R_Mesh_TexBind(1, 0);
12712                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12713                         // generate a color array for the fog pass
12714                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12715                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12716                         RSurf_DrawBatch();
12717                         break;
12718                 default:
12719                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12720                 }
12721         }
12722         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12723         {
12724                 GL_DepthFunc(GL_LEQUAL);
12725                 GL_AlphaTest(false);
12726         }
12727 }
12728
12729 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12730 {
12731         // OpenGL 1.1 - crusty old voodoo path
12732         qboolean applyfog;
12733         int layerindex;
12734         const texturelayer_t *layer;
12735         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);
12736         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12737
12738         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12739         {
12740                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12741                 {
12742                         if (layerindex == 0)
12743                                 GL_AlphaTest(true);
12744                         else
12745                         {
12746                                 GL_AlphaTest(false);
12747                                 GL_DepthFunc(GL_EQUAL);
12748                         }
12749                 }
12750                 GL_DepthMask(layer->depthmask && writedepth);
12751                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12752                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12753                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12754                 switch (layer->type)
12755                 {
12756                 case TEXTURELAYERTYPE_LITTEXTURE:
12757                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12758                         {
12759                                 // two-pass lit texture with 2x rgbscale
12760                                 // first the lightmap pass
12761                                 R_Mesh_TexBind(0, r_texture_white);
12762                                 R_Mesh_TexMatrix(0, NULL);
12763                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12764                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12765                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12766                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12767                                 else if (FAKELIGHT_ENABLED)
12768                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12769                                 else if (rsurface.uselightmaptexture)
12770                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12771                                 else
12772                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12773                                 // then apply the texture to it
12774                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12775                                 R_Mesh_TexBind(0, layer->texture);
12776                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12777                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12778                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12779                                 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);
12780                         }
12781                         else
12782                         {
12783                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12784                                 R_Mesh_TexBind(0, layer->texture);
12785                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12786                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12787                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12788                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12789                                         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);
12790                                 else
12791                                         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);
12792                         }
12793                         break;
12794                 case TEXTURELAYERTYPE_TEXTURE:
12795                         // singletexture unlit texture with transparency support
12796                         R_Mesh_TexBind(0, layer->texture);
12797                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12798                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12799                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12800                         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);
12801                         break;
12802                 case TEXTURELAYERTYPE_FOG:
12803                         // singletexture fogging
12804                         if (layer->texture)
12805                         {
12806                                 R_Mesh_TexBind(0, layer->texture);
12807                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12808                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12809                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12810                         }
12811                         else
12812                         {
12813                                 R_Mesh_TexBind(0, 0);
12814                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12815                         }
12816                         // generate a color array for the fog pass
12817                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12818                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12819                         RSurf_DrawBatch();
12820                         break;
12821                 default:
12822                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12823                 }
12824         }
12825         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12826         {
12827                 GL_DepthFunc(GL_LEQUAL);
12828                 GL_AlphaTest(false);
12829         }
12830 }
12831
12832 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12833 {
12834         int vi;
12835         int j;
12836         r_vertexgeneric_t *batchvertex;
12837         float c[4];
12838
12839         GL_AlphaTest(false);
12840 //      R_Mesh_ResetTextureState();
12841         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12842
12843         if(rsurface.texture && rsurface.texture->currentskinframe)
12844         {
12845                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12846                 c[3] *= rsurface.texture->currentalpha;
12847         }
12848         else
12849         {
12850                 c[0] = 1;
12851                 c[1] = 0;
12852                 c[2] = 1;
12853                 c[3] = 1;
12854         }
12855
12856         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12857         {
12858                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12859                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12860                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12861         }
12862
12863         // brighten it up (as texture value 127 means "unlit")
12864         c[0] *= 2 * r_refdef.view.colorscale;
12865         c[1] *= 2 * r_refdef.view.colorscale;
12866         c[2] *= 2 * r_refdef.view.colorscale;
12867
12868         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12869                 c[3] *= r_wateralpha.value;
12870
12871         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12872         {
12873                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12874                 GL_DepthMask(false);
12875         }
12876         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12877         {
12878                 GL_BlendFunc(GL_ONE, GL_ONE);
12879                 GL_DepthMask(false);
12880         }
12881         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12882         {
12883                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12884                 GL_DepthMask(false);
12885         }
12886         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12887         {
12888                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12889                 GL_DepthMask(false);
12890         }
12891         else
12892         {
12893                 GL_BlendFunc(GL_ONE, GL_ZERO);
12894                 GL_DepthMask(writedepth);
12895         }
12896
12897         if (r_showsurfaces.integer == 3)
12898         {
12899                 rsurface.passcolor4f = NULL;
12900
12901                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12902                 {
12903                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12904
12905                         rsurface.passcolor4f = NULL;
12906                         rsurface.passcolor4f_vertexbuffer = 0;
12907                         rsurface.passcolor4f_bufferoffset = 0;
12908                 }
12909                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12910                 {
12911                         qboolean applycolor = true;
12912                         float one = 1.0;
12913
12914                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12915
12916                         r_refdef.lightmapintensity = 1;
12917                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12918                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12919                 }
12920                 else if (FAKELIGHT_ENABLED)
12921                 {
12922                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12923
12924                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12925                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12926                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12927                 }
12928                 else
12929                 {
12930                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12931
12932                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12933                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12934                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12935                 }
12936
12937                 if(!rsurface.passcolor4f)
12938                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12939
12940                 RSurf_DrawBatch_GL11_ApplyAmbient();
12941                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12942                 if(r_refdef.fogenabled)
12943                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12944                 RSurf_DrawBatch_GL11_ClampColor();
12945
12946                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12947                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12948                 RSurf_DrawBatch();
12949         }
12950         else if (!r_refdef.view.showdebug)
12951         {
12952                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12953                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12954                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12955                 {
12956                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12957                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12958                 }
12959                 R_Mesh_PrepareVertices_Generic_Unlock();
12960                 RSurf_DrawBatch();
12961         }
12962         else if (r_showsurfaces.integer == 4)
12963         {
12964                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12965                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12966                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12967                 {
12968                         unsigned char c = vi << 3;
12969                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12970                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12971                 }
12972                 R_Mesh_PrepareVertices_Generic_Unlock();
12973                 RSurf_DrawBatch();
12974         }
12975         else if (r_showsurfaces.integer == 2)
12976         {
12977                 const int *e;
12978                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12979                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12980                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12981                 {
12982                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12983                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12984                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12985                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12986                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12987                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12988                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12989                 }
12990                 R_Mesh_PrepareVertices_Generic_Unlock();
12991                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12992         }
12993         else
12994         {
12995                 int texturesurfaceindex;
12996                 int k;
12997                 const msurface_t *surface;
12998                 unsigned char surfacecolor4ub[4];
12999                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13000                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13001                 vi = 0;
13002                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13003                 {
13004                         surface = texturesurfacelist[texturesurfaceindex];
13005                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13006                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13007                         for (j = 0;j < surface->num_vertices;j++)
13008                         {
13009                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13010                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13011                                 vi++;
13012                         }
13013                 }
13014                 R_Mesh_PrepareVertices_Generic_Unlock();
13015                 RSurf_DrawBatch();
13016         }
13017 }
13018
13019 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13020 {
13021         CHECKGLERROR
13022         RSurf_SetupDepthAndCulling();
13023         if (r_showsurfaces.integer)
13024         {
13025                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13026                 return;
13027         }
13028         switch (vid.renderpath)
13029         {
13030         case RENDERPATH_GL20:
13031         case RENDERPATH_CGGL:
13032         case RENDERPATH_D3D9:
13033         case RENDERPATH_D3D10:
13034         case RENDERPATH_D3D11:
13035                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13036                 break;
13037         case RENDERPATH_GL13:
13038                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13039                 break;
13040         case RENDERPATH_GL11:
13041                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13042                 break;
13043         }
13044         CHECKGLERROR
13045 }
13046
13047 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13048 {
13049         CHECKGLERROR
13050         RSurf_SetupDepthAndCulling();
13051         if (r_showsurfaces.integer)
13052         {
13053                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13054                 return;
13055         }
13056         switch (vid.renderpath)
13057         {
13058         case RENDERPATH_GL20:
13059         case RENDERPATH_CGGL:
13060         case RENDERPATH_D3D9:
13061         case RENDERPATH_D3D10:
13062         case RENDERPATH_D3D11:
13063                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13064                 break;
13065         case RENDERPATH_GL13:
13066                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13067                 break;
13068         case RENDERPATH_GL11:
13069                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13070                 break;
13071         }
13072         CHECKGLERROR
13073 }
13074
13075 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13076 {
13077         int i, j;
13078         int texturenumsurfaces, endsurface;
13079         texture_t *texture;
13080         const msurface_t *surface;
13081 #define MAXBATCH_TRANSPARENTSURFACES 256
13082         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13083
13084         // if the model is static it doesn't matter what value we give for
13085         // wantnormals and wanttangents, so this logic uses only rules applicable
13086         // to a model, knowing that they are meaningless otherwise
13087         if (ent == r_refdef.scene.worldentity)
13088                 RSurf_ActiveWorldEntity();
13089         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13090                 RSurf_ActiveModelEntity(ent, false, false, false);
13091         else
13092         {
13093                 switch (vid.renderpath)
13094                 {
13095                 case RENDERPATH_GL20:
13096                 case RENDERPATH_CGGL:
13097                 case RENDERPATH_D3D9:
13098                 case RENDERPATH_D3D10:
13099                 case RENDERPATH_D3D11:
13100                         RSurf_ActiveModelEntity(ent, true, true, false);
13101                         break;
13102                 case RENDERPATH_GL13:
13103                 case RENDERPATH_GL11:
13104                         RSurf_ActiveModelEntity(ent, true, false, false);
13105                         break;
13106                 }
13107         }
13108
13109         if (r_transparentdepthmasking.integer)
13110         {
13111                 qboolean setup = false;
13112                 for (i = 0;i < numsurfaces;i = j)
13113                 {
13114                         j = i + 1;
13115                         surface = rsurface.modelsurfaces + surfacelist[i];
13116                         texture = surface->texture;
13117                         rsurface.texture = R_GetCurrentTexture(texture);
13118                         rsurface.lightmaptexture = NULL;
13119                         rsurface.deluxemaptexture = NULL;
13120                         rsurface.uselightmaptexture = false;
13121                         // scan ahead until we find a different texture
13122                         endsurface = min(i + 1024, numsurfaces);
13123                         texturenumsurfaces = 0;
13124                         texturesurfacelist[texturenumsurfaces++] = surface;
13125                         for (;j < endsurface;j++)
13126                         {
13127                                 surface = rsurface.modelsurfaces + surfacelist[j];
13128                                 if (texture != surface->texture)
13129                                         break;
13130                                 texturesurfacelist[texturenumsurfaces++] = surface;
13131                         }
13132                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13133                                 continue;
13134                         // render the range of surfaces as depth
13135                         if (!setup)
13136                         {
13137                                 setup = true;
13138                                 GL_ColorMask(0,0,0,0);
13139                                 GL_Color(1,1,1,1);
13140                                 GL_DepthTest(true);
13141                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13142                                 GL_DepthMask(true);
13143                                 GL_AlphaTest(false);
13144 //                              R_Mesh_ResetTextureState();
13145                                 R_SetupShader_DepthOrShadow();
13146                         }
13147                         RSurf_SetupDepthAndCulling();
13148                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13149                         if (rsurface.batchvertex3fbuffer)
13150                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13151                         else
13152                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13153                         RSurf_DrawBatch();
13154                 }
13155                 if (setup)
13156                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13157         }
13158
13159         for (i = 0;i < numsurfaces;i = j)
13160         {
13161                 j = i + 1;
13162                 surface = rsurface.modelsurfaces + surfacelist[i];
13163                 texture = surface->texture;
13164                 rsurface.texture = R_GetCurrentTexture(texture);
13165                 // scan ahead until we find a different texture
13166                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13167                 texturenumsurfaces = 0;
13168                 texturesurfacelist[texturenumsurfaces++] = surface;
13169                 if(FAKELIGHT_ENABLED)
13170                 {
13171                         rsurface.lightmaptexture = NULL;
13172                         rsurface.deluxemaptexture = NULL;
13173                         rsurface.uselightmaptexture = false;
13174                         for (;j < endsurface;j++)
13175                         {
13176                                 surface = rsurface.modelsurfaces + surfacelist[j];
13177                                 if (texture != surface->texture)
13178                                         break;
13179                                 texturesurfacelist[texturenumsurfaces++] = surface;
13180                         }
13181                 }
13182                 else
13183                 {
13184                         rsurface.lightmaptexture = surface->lightmaptexture;
13185                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13186                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13187                         for (;j < endsurface;j++)
13188                         {
13189                                 surface = rsurface.modelsurfaces + surfacelist[j];
13190                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13191                                         break;
13192                                 texturesurfacelist[texturenumsurfaces++] = surface;
13193                         }
13194                 }
13195                 // render the range of surfaces
13196                 if (ent == r_refdef.scene.worldentity)
13197                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13198                 else
13199                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13200         }
13201         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13202         GL_AlphaTest(false);
13203 }
13204
13205 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13206 {
13207         // transparent surfaces get pushed off into the transparent queue
13208         int surfacelistindex;
13209         const msurface_t *surface;
13210         vec3_t tempcenter, center;
13211         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13212         {
13213                 surface = texturesurfacelist[surfacelistindex];
13214                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13215                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13216                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13217                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13218                 if (queueentity->transparent_offset) // transparent offset
13219                 {
13220                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13221                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13222                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13223                 }
13224                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13225         }
13226 }
13227
13228 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13229 {
13230         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13231                 return;
13232         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13233                 return;
13234         RSurf_SetupDepthAndCulling();
13235         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13236         if (rsurface.batchvertex3fbuffer)
13237                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13238         else
13239                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13240         RSurf_DrawBatch();
13241 }
13242
13243 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13244 {
13245         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13246         CHECKGLERROR
13247         if (depthonly)
13248                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13249         else if (prepass)
13250         {
13251                 if (!rsurface.texture->currentnumlayers)
13252                         return;
13253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13254                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13255                 else
13256                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13257         }
13258         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13259                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13260         else if (!rsurface.texture->currentnumlayers)
13261                 return;
13262         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13263         {
13264                 // in the deferred case, transparent surfaces were queued during prepass
13265                 if (!r_shadow_usingdeferredprepass)
13266                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13267         }
13268         else
13269         {
13270                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13271                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13272         }
13273         CHECKGLERROR
13274 }
13275
13276 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13277 {
13278         int i, j;
13279         texture_t *texture;
13280         R_FrameData_SetMark();
13281         // break the surface list down into batches by texture and use of lightmapping
13282         for (i = 0;i < numsurfaces;i = j)
13283         {
13284                 j = i + 1;
13285                 // texture is the base texture pointer, rsurface.texture is the
13286                 // current frame/skin the texture is directing us to use (for example
13287                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13288                 // use skin 1 instead)
13289                 texture = surfacelist[i]->texture;
13290                 rsurface.texture = R_GetCurrentTexture(texture);
13291                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13292                 {
13293                         // if this texture is not the kind we want, skip ahead to the next one
13294                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13295                                 ;
13296                         continue;
13297                 }
13298                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13299                 {
13300                         rsurface.lightmaptexture = NULL;
13301                         rsurface.deluxemaptexture = NULL;
13302                         rsurface.uselightmaptexture = false;
13303                         // simply scan ahead until we find a different texture or lightmap state
13304                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13305                                 ;
13306                 }
13307                 else
13308                 {
13309                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13310                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13311                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13312                         // simply scan ahead until we find a different texture or lightmap state
13313                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13314                                 ;
13315                 }
13316                 // render the range of surfaces
13317                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13318         }
13319         R_FrameData_ReturnToMark();
13320 }
13321
13322 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13323 {
13324         CHECKGLERROR
13325         if (depthonly)
13326                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13327         else if (prepass)
13328         {
13329                 if (!rsurface.texture->currentnumlayers)
13330                         return;
13331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13332                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13333                 else
13334                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13335         }
13336         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13337                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13338         else if (!rsurface.texture->currentnumlayers)
13339                 return;
13340         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13341         {
13342                 // in the deferred case, transparent surfaces were queued during prepass
13343                 if (!r_shadow_usingdeferredprepass)
13344                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13345         }
13346         else
13347         {
13348                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13349                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13350         }
13351         CHECKGLERROR
13352 }
13353
13354 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13355 {
13356         int i, j;
13357         texture_t *texture;
13358         R_FrameData_SetMark();
13359         // break the surface list down into batches by texture and use of lightmapping
13360         for (i = 0;i < numsurfaces;i = j)
13361         {
13362                 j = i + 1;
13363                 // texture is the base texture pointer, rsurface.texture is the
13364                 // current frame/skin the texture is directing us to use (for example
13365                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13366                 // use skin 1 instead)
13367                 texture = surfacelist[i]->texture;
13368                 rsurface.texture = R_GetCurrentTexture(texture);
13369                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13370                 {
13371                         // if this texture is not the kind we want, skip ahead to the next one
13372                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13373                                 ;
13374                         continue;
13375                 }
13376                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13377                 {
13378                         rsurface.lightmaptexture = NULL;
13379                         rsurface.deluxemaptexture = NULL;
13380                         rsurface.uselightmaptexture = false;
13381                         // simply scan ahead until we find a different texture or lightmap state
13382                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13383                                 ;
13384                 }
13385                 else
13386                 {
13387                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13388                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13389                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13390                         // simply scan ahead until we find a different texture or lightmap state
13391                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13392                                 ;
13393                 }
13394                 // render the range of surfaces
13395                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13396         }
13397         R_FrameData_ReturnToMark();
13398 }
13399
13400 float locboxvertex3f[6*4*3] =
13401 {
13402         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13403         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13404         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13405         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13406         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13407         1,0,0, 0,0,0, 0,1,0, 1,1,0
13408 };
13409
13410 unsigned short locboxelements[6*2*3] =
13411 {
13412          0, 1, 2, 0, 2, 3,
13413          4, 5, 6, 4, 6, 7,
13414          8, 9,10, 8,10,11,
13415         12,13,14, 12,14,15,
13416         16,17,18, 16,18,19,
13417         20,21,22, 20,22,23
13418 };
13419
13420 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13421 {
13422         int i, j;
13423         cl_locnode_t *loc = (cl_locnode_t *)ent;
13424         vec3_t mins, size;
13425         float vertex3f[6*4*3];
13426         CHECKGLERROR
13427         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13428         GL_DepthMask(false);
13429         GL_DepthRange(0, 1);
13430         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13431         GL_DepthTest(true);
13432         GL_CullFace(GL_NONE);
13433         R_EntityMatrix(&identitymatrix);
13434
13435 //      R_Mesh_ResetTextureState();
13436
13437         i = surfacelist[0];
13438         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13439                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13440                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13441                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13442
13443         if (VectorCompare(loc->mins, loc->maxs))
13444         {
13445                 VectorSet(size, 2, 2, 2);
13446                 VectorMA(loc->mins, -0.5f, size, mins);
13447         }
13448         else
13449         {
13450                 VectorCopy(loc->mins, mins);
13451                 VectorSubtract(loc->maxs, loc->mins, size);
13452         }
13453
13454         for (i = 0;i < 6*4*3;)
13455                 for (j = 0;j < 3;j++, i++)
13456                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13457
13458         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13459         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13460         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13461 }
13462
13463 void R_DrawLocs(void)
13464 {
13465         int index;
13466         cl_locnode_t *loc, *nearestloc;
13467         vec3_t center;
13468         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13469         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13470         {
13471                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13472                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13473         }
13474 }
13475
13476 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13477 {
13478         if (decalsystem->decals)
13479                 Mem_Free(decalsystem->decals);
13480         memset(decalsystem, 0, sizeof(*decalsystem));
13481 }
13482
13483 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)
13484 {
13485         tridecal_t *decal;
13486         tridecal_t *decals;
13487         int i;
13488
13489         // expand or initialize the system
13490         if (decalsystem->maxdecals <= decalsystem->numdecals)
13491         {
13492                 decalsystem_t old = *decalsystem;
13493                 qboolean useshortelements;
13494                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13495                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13496                 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)));
13497                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13498                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13499                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13500                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13501                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13502                 if (decalsystem->numdecals)
13503                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13504                 if (old.decals)
13505                         Mem_Free(old.decals);
13506                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13507                         decalsystem->element3i[i] = i;
13508                 if (useshortelements)
13509                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13510                                 decalsystem->element3s[i] = i;
13511         }
13512
13513         // grab a decal and search for another free slot for the next one
13514         decals = decalsystem->decals;
13515         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13516         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13517                 ;
13518         decalsystem->freedecal = i;
13519         if (decalsystem->numdecals <= i)
13520                 decalsystem->numdecals = i + 1;
13521
13522         // initialize the decal
13523         decal->lived = 0;
13524         decal->triangleindex = triangleindex;
13525         decal->surfaceindex = surfaceindex;
13526         decal->decalsequence = decalsequence;
13527         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13528         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13529         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13530         decal->color4ub[0][3] = 255;
13531         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13532         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13533         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13534         decal->color4ub[1][3] = 255;
13535         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13536         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13537         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13538         decal->color4ub[2][3] = 255;
13539         decal->vertex3f[0][0] = v0[0];
13540         decal->vertex3f[0][1] = v0[1];
13541         decal->vertex3f[0][2] = v0[2];
13542         decal->vertex3f[1][0] = v1[0];
13543         decal->vertex3f[1][1] = v1[1];
13544         decal->vertex3f[1][2] = v1[2];
13545         decal->vertex3f[2][0] = v2[0];
13546         decal->vertex3f[2][1] = v2[1];
13547         decal->vertex3f[2][2] = v2[2];
13548         decal->texcoord2f[0][0] = t0[0];
13549         decal->texcoord2f[0][1] = t0[1];
13550         decal->texcoord2f[1][0] = t1[0];
13551         decal->texcoord2f[1][1] = t1[1];
13552         decal->texcoord2f[2][0] = t2[0];
13553         decal->texcoord2f[2][1] = t2[1];
13554 }
13555
13556 extern cvar_t cl_decals_bias;
13557 extern cvar_t cl_decals_models;
13558 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13559 // baseparms, parms, temps
13560 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)
13561 {
13562         int cornerindex;
13563         int index;
13564         float v[9][3];
13565         const float *vertex3f;
13566         int numpoints;
13567         float points[2][9][3];
13568         float temp[3];
13569         float tc[9][2];
13570         float f;
13571         float c[9][4];
13572         const int *e;
13573
13574         e = rsurface.modelelement3i + 3*triangleindex;
13575
13576         vertex3f = rsurface.modelvertex3f;
13577
13578         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13579         {
13580                 index = 3*e[cornerindex];
13581                 VectorCopy(vertex3f + index, v[cornerindex]);
13582         }
13583         // cull backfaces
13584         //TriangleNormal(v[0], v[1], v[2], normal);
13585         //if (DotProduct(normal, localnormal) < 0.0f)
13586         //      continue;
13587         // clip by each of the box planes formed from the projection matrix
13588         // if anything survives, we emit the decal
13589         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]);
13590         if (numpoints < 3)
13591                 return;
13592         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]);
13593         if (numpoints < 3)
13594                 return;
13595         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]);
13596         if (numpoints < 3)
13597                 return;
13598         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]);
13599         if (numpoints < 3)
13600                 return;
13601         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]);
13602         if (numpoints < 3)
13603                 return;
13604         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]);
13605         if (numpoints < 3)
13606                 return;
13607         // some part of the triangle survived, so we have to accept it...
13608         if (dynamic)
13609         {
13610                 // dynamic always uses the original triangle
13611                 numpoints = 3;
13612                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13613                 {
13614                         index = 3*e[cornerindex];
13615                         VectorCopy(vertex3f + index, v[cornerindex]);
13616                 }
13617         }
13618         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13619         {
13620                 // convert vertex positions to texcoords
13621                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13622                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13623                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13624                 // calculate distance fade from the projection origin
13625                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13626                 f = bound(0.0f, f, 1.0f);
13627                 c[cornerindex][0] = r * f;
13628                 c[cornerindex][1] = g * f;
13629                 c[cornerindex][2] = b * f;
13630                 c[cornerindex][3] = 1.0f;
13631                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13632         }
13633         if (dynamic)
13634                 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);
13635         else
13636                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13637                         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);
13638 }
13639 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)
13640 {
13641         matrix4x4_t projection;
13642         decalsystem_t *decalsystem;
13643         qboolean dynamic;
13644         dp_model_t *model;
13645         const msurface_t *surface;
13646         const msurface_t *surfaces;
13647         const int *surfacelist;
13648         const texture_t *texture;
13649         int numtriangles;
13650         int numsurfacelist;
13651         int surfacelistindex;
13652         int surfaceindex;
13653         int triangleindex;
13654         float localorigin[3];
13655         float localnormal[3];
13656         float localmins[3];
13657         float localmaxs[3];
13658         float localsize;
13659         //float normal[3];
13660         float planes[6][4];
13661         float angles[3];
13662         bih_t *bih;
13663         int bih_triangles_count;
13664         int bih_triangles[256];
13665         int bih_surfaces[256];
13666
13667         decalsystem = &ent->decalsystem;
13668         model = ent->model;
13669         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13670         {
13671                 R_DecalSystem_Reset(&ent->decalsystem);
13672                 return;
13673         }
13674
13675         if (!model->brush.data_leafs && !cl_decals_models.integer)
13676         {
13677                 if (decalsystem->model)
13678                         R_DecalSystem_Reset(decalsystem);
13679                 return;
13680         }
13681
13682         if (decalsystem->model != model)
13683                 R_DecalSystem_Reset(decalsystem);
13684         decalsystem->model = model;
13685
13686         RSurf_ActiveModelEntity(ent, false, false, false);
13687
13688         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13689         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13690         VectorNormalize(localnormal);
13691         localsize = worldsize*rsurface.inversematrixscale;
13692         localmins[0] = localorigin[0] - localsize;
13693         localmins[1] = localorigin[1] - localsize;
13694         localmins[2] = localorigin[2] - localsize;
13695         localmaxs[0] = localorigin[0] + localsize;
13696         localmaxs[1] = localorigin[1] + localsize;
13697         localmaxs[2] = localorigin[2] + localsize;
13698
13699         //VectorCopy(localnormal, planes[4]);
13700         //VectorVectors(planes[4], planes[2], planes[0]);
13701         AnglesFromVectors(angles, localnormal, NULL, false);
13702         AngleVectors(angles, planes[0], planes[2], planes[4]);
13703         VectorNegate(planes[0], planes[1]);
13704         VectorNegate(planes[2], planes[3]);
13705         VectorNegate(planes[4], planes[5]);
13706         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13707         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13708         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13709         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13710         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13711         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13712
13713 #if 1
13714 // works
13715 {
13716         matrix4x4_t forwardprojection;
13717         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13718         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13719 }
13720 #else
13721 // broken
13722 {
13723         float projectionvector[4][3];
13724         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13725         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13726         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13727         projectionvector[0][0] = planes[0][0] * ilocalsize;
13728         projectionvector[0][1] = planes[1][0] * ilocalsize;
13729         projectionvector[0][2] = planes[2][0] * ilocalsize;
13730         projectionvector[1][0] = planes[0][1] * ilocalsize;
13731         projectionvector[1][1] = planes[1][1] * ilocalsize;
13732         projectionvector[1][2] = planes[2][1] * ilocalsize;
13733         projectionvector[2][0] = planes[0][2] * ilocalsize;
13734         projectionvector[2][1] = planes[1][2] * ilocalsize;
13735         projectionvector[2][2] = planes[2][2] * ilocalsize;
13736         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13737         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13738         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13739         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13740 }
13741 #endif
13742
13743         dynamic = model->surfmesh.isanimated;
13744         numsurfacelist = model->nummodelsurfaces;
13745         surfacelist = model->sortedmodelsurfaces;
13746         surfaces = model->data_surfaces;
13747
13748         bih = NULL;
13749         bih_triangles_count = -1;
13750         if(!dynamic)
13751         {
13752                 if(model->render_bih.numleafs)
13753                         bih = &model->render_bih;
13754                 else if(model->collision_bih.numleafs)
13755                         bih = &model->collision_bih;
13756         }
13757         if(bih)
13758                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13759         if(bih_triangles_count == 0)
13760                 return;
13761         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13762                 return;
13763         if(bih_triangles_count > 0)
13764         {
13765                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13766                 {
13767                         surfaceindex = bih_surfaces[triangleindex];
13768                         surface = surfaces + surfaceindex;
13769                         texture = surface->texture;
13770                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13771                                 continue;
13772                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13773                                 continue;
13774                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13775                 }
13776         }
13777         else
13778         {
13779                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13780                 {
13781                         surfaceindex = surfacelist[surfacelistindex];
13782                         surface = surfaces + surfaceindex;
13783                         // check cull box first because it rejects more than any other check
13784                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13785                                 continue;
13786                         // skip transparent surfaces
13787                         texture = surface->texture;
13788                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13789                                 continue;
13790                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13791                                 continue;
13792                         numtriangles = surface->num_triangles;
13793                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13794                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13795                 }
13796         }
13797 }
13798
13799 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13800 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)
13801 {
13802         int renderentityindex;
13803         float worldmins[3];
13804         float worldmaxs[3];
13805         entity_render_t *ent;
13806
13807         if (!cl_decals_newsystem.integer)
13808                 return;
13809
13810         worldmins[0] = worldorigin[0] - worldsize;
13811         worldmins[1] = worldorigin[1] - worldsize;
13812         worldmins[2] = worldorigin[2] - worldsize;
13813         worldmaxs[0] = worldorigin[0] + worldsize;
13814         worldmaxs[1] = worldorigin[1] + worldsize;
13815         worldmaxs[2] = worldorigin[2] + worldsize;
13816
13817         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13818
13819         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13820         {
13821                 ent = r_refdef.scene.entities[renderentityindex];
13822                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13823                         continue;
13824
13825                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13826         }
13827 }
13828
13829 typedef struct r_decalsystem_splatqueue_s
13830 {
13831         vec3_t worldorigin;
13832         vec3_t worldnormal;
13833         float color[4];
13834         float tcrange[4];
13835         float worldsize;
13836         int decalsequence;
13837 }
13838 r_decalsystem_splatqueue_t;
13839
13840 int r_decalsystem_numqueued = 0;
13841 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13842
13843 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)
13844 {
13845         r_decalsystem_splatqueue_t *queue;
13846
13847         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13848                 return;
13849
13850         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13851         VectorCopy(worldorigin, queue->worldorigin);
13852         VectorCopy(worldnormal, queue->worldnormal);
13853         Vector4Set(queue->color, r, g, b, a);
13854         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13855         queue->worldsize = worldsize;
13856         queue->decalsequence = cl.decalsequence++;
13857 }
13858
13859 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13860 {
13861         int i;
13862         r_decalsystem_splatqueue_t *queue;
13863
13864         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13865                 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);
13866         r_decalsystem_numqueued = 0;
13867 }
13868
13869 extern cvar_t cl_decals_max;
13870 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13871 {
13872         int i;
13873         decalsystem_t *decalsystem = &ent->decalsystem;
13874         int numdecals;
13875         int killsequence;
13876         tridecal_t *decal;
13877         float frametime;
13878         float lifetime;
13879
13880         if (!decalsystem->numdecals)
13881                 return;
13882
13883         if (r_showsurfaces.integer)
13884                 return;
13885
13886         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13887         {
13888                 R_DecalSystem_Reset(decalsystem);
13889                 return;
13890         }
13891
13892         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13893         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13894
13895         if (decalsystem->lastupdatetime)
13896                 frametime = (cl.time - decalsystem->lastupdatetime);
13897         else
13898                 frametime = 0;
13899         decalsystem->lastupdatetime = cl.time;
13900         decal = decalsystem->decals;
13901         numdecals = decalsystem->numdecals;
13902
13903         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13904         {
13905                 if (decal->color4ub[0][3])
13906                 {
13907                         decal->lived += frametime;
13908                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13909                         {
13910                                 memset(decal, 0, sizeof(*decal));
13911                                 if (decalsystem->freedecal > i)
13912                                         decalsystem->freedecal = i;
13913                         }
13914                 }
13915         }
13916         decal = decalsystem->decals;
13917         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13918                 numdecals--;
13919
13920         // collapse the array by shuffling the tail decals into the gaps
13921         for (;;)
13922         {
13923                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13924                         decalsystem->freedecal++;
13925                 if (decalsystem->freedecal == numdecals)
13926                         break;
13927                 decal[decalsystem->freedecal] = decal[--numdecals];
13928         }
13929
13930         decalsystem->numdecals = numdecals;
13931
13932         if (numdecals <= 0)
13933         {
13934                 // if there are no decals left, reset decalsystem
13935                 R_DecalSystem_Reset(decalsystem);
13936         }
13937 }
13938
13939 extern skinframe_t *decalskinframe;
13940 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13941 {
13942         int i;
13943         decalsystem_t *decalsystem = &ent->decalsystem;
13944         int numdecals;
13945         tridecal_t *decal;
13946         float faderate;
13947         float alpha;
13948         float *v3f;
13949         float *c4f;
13950         float *t2f;
13951         const int *e;
13952         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13953         int numtris = 0;
13954
13955         numdecals = decalsystem->numdecals;
13956         if (!numdecals)
13957                 return;
13958
13959         if (r_showsurfaces.integer)
13960                 return;
13961
13962         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13963         {
13964                 R_DecalSystem_Reset(decalsystem);
13965                 return;
13966         }
13967
13968         // if the model is static it doesn't matter what value we give for
13969         // wantnormals and wanttangents, so this logic uses only rules applicable
13970         // to a model, knowing that they are meaningless otherwise
13971         if (ent == r_refdef.scene.worldentity)
13972                 RSurf_ActiveWorldEntity();
13973         else
13974                 RSurf_ActiveModelEntity(ent, false, false, false);
13975
13976         decalsystem->lastupdatetime = cl.time;
13977         decal = decalsystem->decals;
13978
13979         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13980
13981         // update vertex positions for animated models
13982         v3f = decalsystem->vertex3f;
13983         c4f = decalsystem->color4f;
13984         t2f = decalsystem->texcoord2f;
13985         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13986         {
13987                 if (!decal->color4ub[0][3])
13988                         continue;
13989
13990                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13991                         continue;
13992
13993                 // update color values for fading decals
13994                 if (decal->lived >= cl_decals_time.value)
13995                 {
13996                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13997                         alpha *= (1.0f/255.0f);
13998                 }
13999                 else
14000                         alpha = 1.0f/255.0f;
14001
14002                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14003                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14004                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14005                 c4f[ 3] = 1;
14006                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14007                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14008                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14009                 c4f[ 7] = 1;
14010                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14011                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14012                 c4f[10] = decal->color4ub[2][2] * alpha;
14013                 c4f[11] = 1;
14014
14015                 t2f[0] = decal->texcoord2f[0][0];
14016                 t2f[1] = decal->texcoord2f[0][1];
14017                 t2f[2] = decal->texcoord2f[1][0];
14018                 t2f[3] = decal->texcoord2f[1][1];
14019                 t2f[4] = decal->texcoord2f[2][0];
14020                 t2f[5] = decal->texcoord2f[2][1];
14021
14022                 // update vertex positions for animated models
14023                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14024                 {
14025                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14026                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14027                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14028                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14029                 }
14030                 else
14031                 {
14032                         VectorCopy(decal->vertex3f[0], v3f);
14033                         VectorCopy(decal->vertex3f[1], v3f + 3);
14034                         VectorCopy(decal->vertex3f[2], v3f + 6);
14035                 }
14036
14037                 if (r_refdef.fogenabled)
14038                 {
14039                         alpha = RSurf_FogVertex(v3f);
14040                         VectorScale(c4f, alpha, c4f);
14041                         alpha = RSurf_FogVertex(v3f + 3);
14042                         VectorScale(c4f + 4, alpha, c4f + 4);
14043                         alpha = RSurf_FogVertex(v3f + 6);
14044                         VectorScale(c4f + 8, alpha, c4f + 8);
14045                 }
14046
14047                 v3f += 9;
14048                 c4f += 12;
14049                 t2f += 6;
14050                 numtris++;
14051         }
14052
14053         if (numtris > 0)
14054         {
14055                 r_refdef.stats.drawndecals += numtris;
14056
14057                 // now render the decals all at once
14058                 // (this assumes they all use one particle font texture!)
14059                 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);
14060 //              R_Mesh_ResetTextureState();
14061                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14062                 GL_DepthMask(false);
14063                 GL_DepthRange(0, 1);
14064                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14065                 GL_DepthTest(true);
14066                 GL_CullFace(GL_NONE);
14067                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14068                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14069                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14070         }
14071 }
14072
14073 static void R_DrawModelDecals(void)
14074 {
14075         int i, numdecals;
14076
14077         // fade faster when there are too many decals
14078         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14079         for (i = 0;i < r_refdef.scene.numentities;i++)
14080                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14081
14082         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14083         for (i = 0;i < r_refdef.scene.numentities;i++)
14084                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14085                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14086
14087         R_DecalSystem_ApplySplatEntitiesQueue();
14088
14089         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14090         for (i = 0;i < r_refdef.scene.numentities;i++)
14091                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14092
14093         r_refdef.stats.totaldecals += numdecals;
14094
14095         if (r_showsurfaces.integer)
14096                 return;
14097
14098         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14099
14100         for (i = 0;i < r_refdef.scene.numentities;i++)
14101         {
14102                 if (!r_refdef.viewcache.entityvisible[i])
14103                         continue;
14104                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14105                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14106         }
14107 }
14108
14109 extern cvar_t mod_collision_bih;
14110 void R_DrawDebugModel(void)
14111 {
14112         entity_render_t *ent = rsurface.entity;
14113         int i, j, k, l, flagsmask;
14114         const msurface_t *surface;
14115         dp_model_t *model = ent->model;
14116         vec3_t v;
14117
14118         switch(vid.renderpath)
14119         {
14120         case RENDERPATH_GL11:
14121         case RENDERPATH_GL13:
14122         case RENDERPATH_GL20:
14123         case RENDERPATH_CGGL:
14124                 break;
14125         case RENDERPATH_D3D9:
14126                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14127                 return;
14128         case RENDERPATH_D3D10:
14129                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14130                 return;
14131         case RENDERPATH_D3D11:
14132                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14133                 return;
14134         }
14135
14136         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14137
14138 //      R_Mesh_ResetTextureState();
14139         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14140         GL_DepthRange(0, 1);
14141         GL_DepthTest(!r_showdisabledepthtest.integer);
14142         GL_DepthMask(false);
14143         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14144
14145         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14146         {
14147                 int triangleindex;
14148                 int bihleafindex;
14149                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14150                 const q3mbrush_t *brush;
14151                 const bih_t *bih = &model->collision_bih;
14152                 const bih_leaf_t *bihleaf;
14153                 float vertex3f[3][3];
14154                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14155                 cullbox = false;
14156                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14157                 {
14158                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14159                                 continue;
14160                         switch (bihleaf->type)
14161                         {
14162                         case BIH_BRUSH:
14163                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14164                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14165                                 {
14166                                         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);
14167                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14168                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14169                                 }
14170                                 break;
14171                         case BIH_COLLISIONTRIANGLE:
14172                                 triangleindex = bihleaf->itemindex;
14173                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14174                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14175                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14176                                 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);
14177                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14178                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14179                                 break;
14180                         case BIH_RENDERTRIANGLE:
14181                                 triangleindex = bihleaf->itemindex;
14182                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14183                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14184                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14185                                 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);
14186                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14187                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14188                                 break;
14189                         }
14190                 }
14191         }
14192
14193         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14194
14195         if (r_showtris.integer || (r_shownormals.value != 0))
14196         {
14197                 if (r_showdisabledepthtest.integer)
14198                 {
14199                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14200                         GL_DepthMask(false);
14201                 }
14202                 else
14203                 {
14204                         GL_BlendFunc(GL_ONE, GL_ZERO);
14205                         GL_DepthMask(true);
14206                 }
14207                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14208                 {
14209                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14210                                 continue;
14211                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14212                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14213                         {
14214                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14215                                 if (r_showtris.value > 0)
14216                                 {
14217                                         if (!rsurface.texture->currentlayers->depthmask)
14218                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14219                                         else if (ent == r_refdef.scene.worldentity)
14220                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14221                                         else
14222                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14223                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14224                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14225                                         RSurf_DrawBatch();
14226                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14227                                         CHECKGLERROR
14228                                 }
14229                                 if (r_shownormals.value < 0)
14230                                 {
14231                                         qglBegin(GL_LINES);
14232                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14233                                         {
14234                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14235                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14236                                                 qglVertex3f(v[0], v[1], v[2]);
14237                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14238                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14239                                                 qglVertex3f(v[0], v[1], v[2]);
14240                                         }
14241                                         qglEnd();
14242                                         CHECKGLERROR
14243                                 }
14244                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14245                                 {
14246                                         qglBegin(GL_LINES);
14247                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14248                                         {
14249                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14250                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14251                                                 qglVertex3f(v[0], v[1], v[2]);
14252                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14253                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14254                                                 qglVertex3f(v[0], v[1], v[2]);
14255                                         }
14256                                         qglEnd();
14257                                         CHECKGLERROR
14258                                         qglBegin(GL_LINES);
14259                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14260                                         {
14261                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14262                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14263                                                 qglVertex3f(v[0], v[1], v[2]);
14264                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14265                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14266                                                 qglVertex3f(v[0], v[1], v[2]);
14267                                         }
14268                                         qglEnd();
14269                                         CHECKGLERROR
14270                                         qglBegin(GL_LINES);
14271                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14272                                         {
14273                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14274                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14275                                                 qglVertex3f(v[0], v[1], v[2]);
14276                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14277                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14278                                                 qglVertex3f(v[0], v[1], v[2]);
14279                                         }
14280                                         qglEnd();
14281                                         CHECKGLERROR
14282                                 }
14283                         }
14284                 }
14285                 rsurface.texture = NULL;
14286         }
14287 }
14288
14289 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14290 int r_maxsurfacelist = 0;
14291 const msurface_t **r_surfacelist = NULL;
14292 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14293 {
14294         int i, j, endj, flagsmask;
14295         dp_model_t *model = r_refdef.scene.worldmodel;
14296         msurface_t *surfaces;
14297         unsigned char *update;
14298         int numsurfacelist = 0;
14299         if (model == NULL)
14300                 return;
14301
14302         if (r_maxsurfacelist < model->num_surfaces)
14303         {
14304                 r_maxsurfacelist = model->num_surfaces;
14305                 if (r_surfacelist)
14306                         Mem_Free((msurface_t**)r_surfacelist);
14307                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14308         }
14309
14310         RSurf_ActiveWorldEntity();
14311
14312         surfaces = model->data_surfaces;
14313         update = model->brushq1.lightmapupdateflags;
14314
14315         // update light styles on this submodel
14316         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14317         {
14318                 model_brush_lightstyleinfo_t *style;
14319                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14320                 {
14321                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14322                         {
14323                                 int *list = style->surfacelist;
14324                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14325                                 for (j = 0;j < style->numsurfaces;j++)
14326                                         update[list[j]] = true;
14327                         }
14328                 }
14329         }
14330
14331         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14332
14333         if (debug)
14334         {
14335                 R_DrawDebugModel();
14336                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14337                 return;
14338         }
14339
14340         rsurface.lightmaptexture = NULL;
14341         rsurface.deluxemaptexture = NULL;
14342         rsurface.uselightmaptexture = false;
14343         rsurface.texture = NULL;
14344         rsurface.rtlight = NULL;
14345         numsurfacelist = 0;
14346         // add visible surfaces to draw list
14347         for (i = 0;i < model->nummodelsurfaces;i++)
14348         {
14349                 j = model->sortedmodelsurfaces[i];
14350                 if (r_refdef.viewcache.world_surfacevisible[j])
14351                         r_surfacelist[numsurfacelist++] = surfaces + j;
14352         }
14353         // update lightmaps if needed
14354         if (model->brushq1.firstrender)
14355         {
14356                 model->brushq1.firstrender = false;
14357                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14358                         if (update[j])
14359                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14360         }
14361         else if (update)
14362         {
14363                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14364                         if (r_refdef.viewcache.world_surfacevisible[j])
14365                                 if (update[j])
14366                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14367         }
14368         // don't do anything if there were no surfaces
14369         if (!numsurfacelist)
14370         {
14371                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14372                 return;
14373         }
14374         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14375         GL_AlphaTest(false);
14376
14377         // add to stats if desired
14378         if (r_speeds.integer && !skysurfaces && !depthonly)
14379         {
14380                 r_refdef.stats.world_surfaces += numsurfacelist;
14381                 for (j = 0;j < numsurfacelist;j++)
14382                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14383         }
14384
14385         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14386 }
14387
14388 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14389 {
14390         int i, j, endj, flagsmask;
14391         dp_model_t *model = ent->model;
14392         msurface_t *surfaces;
14393         unsigned char *update;
14394         int numsurfacelist = 0;
14395         if (model == NULL)
14396                 return;
14397
14398         if (r_maxsurfacelist < model->num_surfaces)
14399         {
14400                 r_maxsurfacelist = model->num_surfaces;
14401                 if (r_surfacelist)
14402                         Mem_Free((msurface_t **)r_surfacelist);
14403                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14404         }
14405
14406         // if the model is static it doesn't matter what value we give for
14407         // wantnormals and wanttangents, so this logic uses only rules applicable
14408         // to a model, knowing that they are meaningless otherwise
14409         if (ent == r_refdef.scene.worldentity)
14410                 RSurf_ActiveWorldEntity();
14411         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14412                 RSurf_ActiveModelEntity(ent, false, false, false);
14413         else if (prepass)
14414                 RSurf_ActiveModelEntity(ent, true, true, true);
14415         else if (depthonly)
14416         {
14417                 switch (vid.renderpath)
14418                 {
14419                 case RENDERPATH_GL20:
14420                 case RENDERPATH_CGGL:
14421                 case RENDERPATH_D3D9:
14422                 case RENDERPATH_D3D10:
14423                 case RENDERPATH_D3D11:
14424                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14425                         break;
14426                 case RENDERPATH_GL13:
14427                 case RENDERPATH_GL11:
14428                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14429                         break;
14430                 }
14431         }
14432         else
14433         {
14434                 switch (vid.renderpath)
14435                 {
14436                 case RENDERPATH_GL20:
14437                 case RENDERPATH_CGGL:
14438                 case RENDERPATH_D3D9:
14439                 case RENDERPATH_D3D10:
14440                 case RENDERPATH_D3D11:
14441                         RSurf_ActiveModelEntity(ent, true, true, false);
14442                         break;
14443                 case RENDERPATH_GL13:
14444                 case RENDERPATH_GL11:
14445                         RSurf_ActiveModelEntity(ent, true, false, false);
14446                         break;
14447                 }
14448         }
14449
14450         surfaces = model->data_surfaces;
14451         update = model->brushq1.lightmapupdateflags;
14452
14453         // update light styles
14454         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14455         {
14456                 model_brush_lightstyleinfo_t *style;
14457                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14458                 {
14459                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14460                         {
14461                                 int *list = style->surfacelist;
14462                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14463                                 for (j = 0;j < style->numsurfaces;j++)
14464                                         update[list[j]] = true;
14465                         }
14466                 }
14467         }
14468
14469         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14470
14471         if (debug)
14472         {
14473                 R_DrawDebugModel();
14474                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14475                 return;
14476         }
14477
14478         rsurface.lightmaptexture = NULL;
14479         rsurface.deluxemaptexture = NULL;
14480         rsurface.uselightmaptexture = false;
14481         rsurface.texture = NULL;
14482         rsurface.rtlight = NULL;
14483         numsurfacelist = 0;
14484         // add visible surfaces to draw list
14485         for (i = 0;i < model->nummodelsurfaces;i++)
14486                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14487         // don't do anything if there were no surfaces
14488         if (!numsurfacelist)
14489         {
14490                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14491                 return;
14492         }
14493         // update lightmaps if needed
14494         if (update)
14495         {
14496                 int updated = 0;
14497                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14498                 {
14499                         if (update[j])
14500                         {
14501                                 updated++;
14502                                 R_BuildLightMap(ent, surfaces + j);
14503                         }
14504                 }
14505         }
14506         if (update)
14507                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14508                         if (update[j])
14509                                 R_BuildLightMap(ent, surfaces + j);
14510         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14511         GL_AlphaTest(false);
14512
14513         // add to stats if desired
14514         if (r_speeds.integer && !skysurfaces && !depthonly)
14515         {
14516                 r_refdef.stats.entities_surfaces += numsurfacelist;
14517                 for (j = 0;j < numsurfacelist;j++)
14518                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14519         }
14520
14521         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14522 }
14523
14524 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14525 {
14526         static texture_t texture;
14527         static msurface_t surface;
14528         const msurface_t *surfacelist = &surface;
14529
14530         // fake enough texture and surface state to render this geometry
14531
14532         texture.update_lastrenderframe = -1; // regenerate this texture
14533         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14534         texture.currentskinframe = skinframe;
14535         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14536         texture.offsetmapping = OFFSETMAPPING_OFF;
14537         texture.offsetscale = 1;
14538         texture.specularscalemod = 1;
14539         texture.specularpowermod = 1;
14540
14541         surface.texture = &texture;
14542         surface.num_triangles = numtriangles;
14543         surface.num_firsttriangle = firsttriangle;
14544         surface.num_vertices = numvertices;
14545         surface.num_firstvertex = firstvertex;
14546
14547         // now render it
14548         rsurface.texture = R_GetCurrentTexture(surface.texture);
14549         rsurface.lightmaptexture = NULL;
14550         rsurface.deluxemaptexture = NULL;
14551         rsurface.uselightmaptexture = false;
14552         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14553 }
14554
14555 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)
14556 {
14557         static msurface_t surface;
14558         const msurface_t *surfacelist = &surface;
14559
14560         // fake enough texture and surface state to render this geometry
14561         surface.texture = texture;
14562         surface.num_triangles = numtriangles;
14563         surface.num_firsttriangle = firsttriangle;
14564         surface.num_vertices = numvertices;
14565         surface.num_firstvertex = firstvertex;
14566
14567         // now render it
14568         rsurface.texture = R_GetCurrentTexture(surface.texture);
14569         rsurface.lightmaptexture = NULL;
14570         rsurface.deluxemaptexture = NULL;
14571         rsurface.uselightmaptexture = false;
14572         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14573 }